26 #include <Classes.hpp>
27 #include <Controls.hpp>
28 #include <StdCtrls.hpp>
30 #include <Buttons.hpp>
31 #include <ExtCtrls.hpp>
33 #include <Dialogs.hpp>
34 #include <Graphics.hpp>
35 #include <ComCtrls.hpp>
53 #pragma package(smart_init)
72 TTrain::TTrain(
int Caller,
int RearStartElementIn,
int RearStartExitPosIn, AnsiString InputCode,
int StartSpeedIn,
int MassIn,
double MaxRunningSpeedIn,
73 double MaxBrakeRateIn,
double PowerAtRailIn,
TTrainMode TrainModeIn,
TTrainDataEntry *TrainDataEntryPtrIn,
int RepeatNumberIn,
int IncrementalMinutesIn,
74 int IncrementalDigitsIn,
int SignallerMaxSpeedIn) : RearStartElement(RearStartElementIn), RearStartExitPos(RearStartExitPosIn), HeadCode(InputCode),
75 StartSpeed(StartSpeedIn), Mass(MassIn), MaxRunningSpeed(MaxRunningSpeedIn), MaxBrakeRate(MaxBrakeRateIn), PowerAtRail(PowerAtRailIn),
76 TrainMode(TrainModeIn), TrainDataEntryPtr(TrainDataEntryPtrIn), RepeatNumber(RepeatNumberIn), IncrementalMinutes(IncrementalMinutesIn),
77 IncrementalDigits(IncrementalDigitsIn), SignallerMaxSpeed(SignallerMaxSpeedIn)
88 AnsiString(RearStartExitPosIn) +
"," + AnsiString(InputCode) +
"," + AnsiString(StartSpeedIn) +
"," + AnsiString(MassIn) +
"," +
89 AnsiString(TrainModeIn));
135 for(
int x = 0; x < 4; x++)
144 for(
int x = 0; x < 4; x++)
153 for(
int x = 0; x < 4; x++)
158 for(
int x = 0; x < 4; x++)
162 for(
int x = 0; x < 3; x++)
199 for(
int x = 0; x < 4; x++)
258 throw Exception(
"Error in attempting to delete FrontCodePtr");
262 for(
int x = 0; x < 4; x++)
266 throw Exception(
"Error in attempting to delete BackgroundPtr[" + AnsiString(x) +
"]");
271 for(
int x = 0; x < 4; x++)
275 throw Exception(
"Error in attempting to delete HeadCodeGrPtr[" + AnsiString(x) +
"]");
304 int NextElementPosition, NextEntryPos, ElementLength, SpeedLimit;
370 bool TempDerail =
false;
416 else if((NextElementPosition > -1) && (NextEntryPos > -1))
487 throw Exception(
"Error, LeadElement Exit Connection is NotSet");
497 for(
int x = 0; x < 4; x++)
504 for(
int x = 0; x < 4; x++)
765 int LockedVectorNumber;
894 AnsiString ReasonArray[24] = {
"a driver is awaited",
"a guard is awaited",
"of a medical emergency",
"of a technical problem",
"of a security issue",
895 "of a safety issue",
"of a disturbance",
"a train crew member has been taken ill",
"the driver has been taken ill",
"the guard has been taken ill",
896 "a report has been received concerning safety",
"a shoe has been lost under the train",
"of a reported theft",
897 "of an incident involving an animal",
"some luggage has been lost under the train",
"a minor repair is needed",
"a suspicious object has to be dealt with safely",
898 "a door is stuck open",
"additional stock has to be attached",
"a security alert",
"of a train fault",
"of an operating incident",
"safety checks are required",
899 "of a shortage of on train crew"};
906 if(DwellTime < TDateTime(30.0 / 86400))
908 DwellTime = TDateTime(30.0 / 86400);
910 int randval = random(10000);
915 if(randval < Utilities->MinorDelayCutoff)
922 if(randval < Utilities->ModerateDelayCutoff)
929 if(randval < Utilities->MajorDelayCutoff)
944 if(
NewDelay <
double(DwellTime) * 1440)
950 NewDelay -= double(DwellTime) * 1440;
1011 int randval2 = rand() % 24;
1012 AnsiString Reason = ReasonArray[randval2];
1015 " minutes because " + Reason);
1017 " minutes because " + Reason);
1023 " minutes because of a minor problem");
1025 " minutes because of a minor problem");
1175 if(BufferLocation ==
"")
1180 if((BufferLocation ==
"") || (BufferLocation != ExpectedLocation))
1242 int NextElementPosition, NextEntryPos;
1266 NextElementPosition = -1;
1269 if((NextElementPosition > -1) && (NextEntryPos > -1))
1391 AnsiString StationName;
1402 throw Exception(
"Error - Stopped at through station but neither lead nor mid elements have a name");
1415 if((NextElementPosition > -1) && (NextEntryPos > -1))
1549 if(TIFEntryPos == 0)
1586 if(NextElementPosition > -1)
1623 AnsiString Loc =
"";
1624 bool LocNamed =
false;
1653 Loc =
"outside railway";
1685 NextElementPosition = -1;
1696 if((NextElementPosition > -1) && (NextEntryPos > -1) && !
SPADFlag)
1714 if((NextElementPosition > -1) && (NextEntryPos > -1))
1752 FirstPair.second).
GetELink() == TempELink))
1757 SecondPair.second).
GetELink() == TempELink))
1771 FirstPair.second).
GetELink() == TempELink))
1776 SecondPair.second).
GetELink() == TempELink))
1790 FirstPair.second).
GetELink() == TempELink))
1795 SecondPair.second).
GetELink() == TempELink))
1825 ContinuationAutoSigEntry.
RouteNumber = RouteNumber;
1828 int NewLastElement = 0, NewLastExitPos = 0;
1846 if(NewLastElement == -1)
1852 if(NewLastExitPos == -1)
1856 LastElement = NewLastElement;
1857 LastExitPos = NewLastExitPos;
1860 if(CumDistance < 1200)
1866 int FirstDistance = 0;
1867 if(CumDistance >= 1200)
1869 FirstDistance = 100;
1873 FirstDistance = 1200 - CumDistance;
1875 if(FirstDistance < 100)
1877 FirstDistance = 100;
1903 if(VectorIT->RouteNumber == RouteNumber)
1940 " failed when changing aspect.\nTrains can only pass under signaller control.");
1974 LockedVectorNumber)))
2133 for(
int x = 0; x < 4; x++)
2140 for(
int x = 0; x < 4; x++)
2166 if((LeadElementTrainID > -1) && (LeadElementTrainID !=
TrainID))
2171 if(OtherTrainEntryPos == -1)
2173 throw Exception(
"Error - OtherTrainEntryPos not set");
2192 int OtherTrainID = -1;
2193 if((MidExitLinkNum == 1) || (MidExitLinkNum == 3) || (MidExitLinkNum == 7) || (MidExitLinkNum == 9))
2284 bool StopRequired =
false;
2297 int NextElementEntryPos = -1;
2298 int NextElementExitPos = -1;
2299 bool TrainOnNextElement =
false;
2300 bool StopSignalAtNextElement =
false;
2301 if(ForwardConnection)
2309 StopSignalAtNextElement = ((NextTrackElement.
Config[NextElementExitPos] ==
Signal) && (NextTrackElement.
Attribute == 0));
2311 if(TrainAtStopLinkPos1 || TrainAtStopLinkPos2 || (ForwardConnection && (TrainOnNextElement || StopSignalAtNextElement)))
2367 throw Exception(
"Error, Straddle shouldn't be LeadMid prior to resetting at exit from UpdateTrain");
2580 if(Code.Length() != 4)
2584 for(
int x = 1; x < 5; x++)
2591 for(
int x = 0; x < 4; x++)
2754 throw Exception(
"Error in GetOffsetValues - Link value wrong");
2767 if((EntryLink == 1) || (EntryLink == 2) || (EntryLink == 4) || (EntryLink == 7))
2782 AnsiString(
VOffset) +
"," + AnsiString(Element) +
"," + AnsiString(EntryPos) +
"," +
HeadCode);
2791 TRect SourceRect, DestRect;
2793 DestRect.init(0, 0, 8, 8);
2796 Graphics::TBitmap *TempGraphic =
new Graphics::TBitmap;
2798 TempGraphic->PixelFormat = pf8bit;
2799 TempGraphic->Width = 16;
2800 TempGraphic->Height = 16;
2806 TempGraphic->Transparent =
true;
2810 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2811 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2817 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2825 else if(TempElement.
SpeedTag == 89)
2829 else if(TempElement.
SpeedTag == 90)
2833 else if(TempElement.
SpeedTag == 91)
2837 else if(TempElement.
SpeedTag == 92)
2841 else if(TempElement.
SpeedTag == 93)
2845 else if(TempElement.
SpeedTag == 94)
2849 else if(TempElement.
SpeedTag == 95)
2853 TempGraphic->Transparent =
true;
2857 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2858 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2860 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2867 for(
int x = 0; x < 40; x++)
2882 TempGraphic->Transparent =
true;
2886 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2887 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2889 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2903 TempGraphic->Transparent =
true;
2907 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2908 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2912 TempGraphic->Canvas->Draw(0, 0, TempElement.
GraphicPtr);
2915 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2920 TempGraphic->Transparent =
true;
2924 int BDVectorPos = -1;
2933 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2938 TempGraphic->Transparent =
true;
2942 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2943 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2945 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
2951 TempGraphic->Transparent =
true;
2955 TempGraphic->Canvas->Draw(0, 0, EXGraphicPtr);
2956 TempGraphic->Canvas->Draw(0, 0, EntryDirectionGraphicPtr);
2958 GraphicPtr->Canvas->CopyRect(DestRect, TempGraphic->Canvas, SourceRect);
3224 throw Exception(
"Error, same train on two different bridge tracks");
3270 AnsiString(EntryPos) +
"," +
HeadCode);
3287 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in SetTrainElementID");
3306 AnsiString(EntryPos) +
"," +
HeadCode);
3315 throw Exception(
"Error, TrackVectorPosition set but not EntryPos in ResetTrainElementID");
3348 AnsiString(ElementEntryPos) +
"," + AnsiString(
HOffset) +
"," + AnsiString(
VOffset) +
"," + AnsiString(StraddleValue) +
"," +
HeadCode);
3349 int LockedVectorNumber;
3362 TRect SourceRect, DestRect;
3363 DestRect.init(0, 0, 8, 8);
3370 int FirstELink, SecondELink = -1;
3373 if(RoutePair2.first > -1)
3382 if(SecondELink == -1)
3384 throw Exception(
"Error - Second ELink should be set but isn't in PlotAlternativeTrackRouteGraphic [1]");
3389 throw Exception(
"Error - First & Second ELinks have same value in PlotAlternativeTrackRouteGraphic");
3399 Graphics::TBitmap *DestGraphic =
new Graphics::TBitmap;
3400 DestGraphic->PixelFormat = pf8bit;
3401 DestGraphic->Width = 8;
3402 DestGraphic->Height = 8;
3403 DestGraphic->Transparent =
true;
3406 DestGraphic->Canvas->CopyRect(DestRect, RouteElement.
GetRouteEXGraphicPtr()->Canvas, SourceRect);
3415 PrefDirElement, LockedVectorNumber))
3430 if(ElementEntryPos > 1)
3452 AnsiString(EntryPos) +
"," +
HeadCode);
3454 bool WrongRoute =
false;
3480 int LinkNumber = TrackElement.
Link[EntryPos];
3481 if((LinkNumber == 1) || (LinkNumber == 3) || (LinkNumber == 7) || (LinkNumber == 9))
3486 bool LogActionErrorCalled =
false;
3496 LogActionErrorCalled =
true;
3513 else if(LinkNumber == 3)
3521 LogActionErrorCalled =
true;
3538 else if(LinkNumber == 7)
3546 LogActionErrorCalled =
true;
3563 else if(LinkNumber == 9)
3571 LogActionErrorCalled =
true;
3603 else if((RouteElement.
GetELinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3608 else if((RouteElement.
GetELinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3618 else if((RouteElement.
GetXLinkPos() == 2) && (EntryPos == 0) && PointsAtElement)
3623 else if((RouteElement.
GetXLinkPos() == 0) && (EntryPos == 2) && PointsAtElement)
3632 throw Exception(
"Error, Element in route but no route found in CheckAndCancelRouteForWrongEndEntry");
3653 bool ColourError =
false, ColourError2 =
false;
3658 ColourError2 =
true;
3660 for(
int x = 0; x < 4; x++)
3665 ColourError2 =
true;
3671 "ERROR: Colour depth insufficient to display train colours properly. Please ensure that the 'safe' (web) palette of 256 colours can be displayed");
3675 for(
int x = 0; x < 4; x++)
3762 AnsiString(EntryPos) +
"," +
HeadCode);
3763 int EntryHalfLength, CurrentElementHalfLength, NextElementHalfLength, CumulativeLength = 0, CurrentTrackVectorPosition = TrackVectorPosition;
3764 int DistanceAtHalfBraking, DistanceAtThreeQuarterBraking, ExitPos, NextTrackVectorPosition, NextEntryPos;
3765 bool RedSignalFlag =
false, BuffersFlag =
false, StationFlag =
false, BuffersOrContinuationNowFlag =
false, ContinuationNextFlag =
false,
3766 TrainInFrontInSignallerModeFlag =
false;
3767 double LimitingSpeed, FrontElementMaxSpeed, MaxExitSpeedAtHalfBrakingSquared, MaxExitSpeedAtHalfBraking, NextSpeedLimit, TempBrakeRate;
3768 double ExitSpeedHalfSquared, ExitSpeedFullSquared;
3769 bool SignallerStopRequired =
false;
3780 if(CurrentTrackVectorPosition > -1)
3784 if((EntryPos == 0) || (EntryPos == 2))
3797 else if(EntryPos == 1)
3821 EntryHalfLength = CurrentElementHalfLength;
3826 throw Exception(
"Error - CurrentTrackVectorPosition < 0 in SetTrainMovementValues");
3830 throw Exception(
"Error - HalfLength or SpeedLimit < 0 in SetTrainMovementValues");
3877 FrontElementMaxSpeed = LimitingSpeed;
3913 double ExitSpeedAtMaxBraking;
3918 ExitSpeedAtMaxBraking = 0;
3928 if(ExitSpeedAtMaxBraking > LimitingSpeed)
3930 SpeedToUse = ExitSpeedAtMaxBraking;
3934 SpeedToUse = LimitingSpeed;
3949 RedSignalFlag =
false;
3950 BuffersFlag =
false;
3951 StationFlag =
false;
3952 BuffersOrContinuationNowFlag =
false;
3953 ContinuationNextFlag =
false;
3956 CumulativeLength += (2 * CurrentElementHalfLength);
3959 SignallerStopRequired =
true;
3981 bool StopRequired =
false;
3995 StationFlag =
false;
4001 BuffersOrContinuationNowFlag =
true;
4003 if(!BuffersOrContinuationNowFlag && !BuffersFlag && !StationFlag)
4007 if((EntryPos == 0) || (EntryPos == 2))
4029 if(NextTrackVectorPosition > -1)
4034 if((NextEntryPos == 0) || (NextEntryPos == 2))
4047 else if(NextEntryPos == 1)
4060 if(NextEntryPos > 1)
4074 throw Exception(
"Error - Trying to access NextTrackVectorPosition when none present in SetTrainMovementValues");
4086 RedSignalFlag =
true;
4108 TrainInFrontInSignallerModeFlag =
true;
4132 if(RedSignalFlag || BuffersFlag || StationFlag || TrainInFrontInSignallerModeFlag || SignallerStopRequired ||
StepForwardFlag)
4144 double MaxHalfSpeed;
4148 if(MaxHalfSpeedAtHalfBraking > FrontElementMaxSpeed)
4150 MaxHalfSpeed = FrontElementMaxSpeed;
4154 MaxHalfSpeed = MaxHalfSpeedAtHalfBraking;
4162 bool HalfSpeedLimited =
false;
4166 HalfSpeedLimited =
true;
4196 if(HalfSpeedLimited)
4221 if(SignallerStopRequired)
4237 int TempMaxExitSpeed;
4240 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4242 MaxExitSpeedAtHalfBraking = 0;
4246 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4250 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4252 TempMaxExitSpeed = FrontElementMaxSpeed;
4256 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4268 if(ExitSpeedHalfSquared < 10)
4278 if(ExitSpeedFullSquared < 10)
4350 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4351 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4375 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4376 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4386 if(!BuffersOrContinuationNowFlag)
4388 if(NextSpeedLimit < LimitingSpeed)
4390 LimitingSpeed = NextSpeedLimit;
4394 int TempMaxExitSpeed;
4398 if(MaxExitSpeedAtHalfBrakingSquared < 10)
4400 MaxExitSpeedAtHalfBraking = 0;
4404 MaxExitSpeedAtHalfBraking = sqrt(MaxExitSpeedAtHalfBrakingSquared);
4406 if(MaxExitSpeedAtHalfBraking > FrontElementMaxSpeed)
4408 TempMaxExitSpeed = FrontElementMaxSpeed;
4412 TempMaxExitSpeed = MaxExitSpeedAtHalfBraking;
4423 TempBrakeRate = ((
EntrySpeed *
EntrySpeed) - (LimitingSpeed * LimitingSpeed)) / 3.6 / 3.6 / 2 / CumulativeLength;
4436 if(!BuffersOrContinuationNowFlag)
4438 CurrentTrackVectorPosition = NextTrackVectorPosition;
4439 EntryPos = NextEntryPos;
4440 CurrentElementHalfLength = NextElementHalfLength;
4443 ContinuationNextFlag =
true;
4447 while(((CumulativeLength -
FrontElementLength) < DistanceAtHalfBraking) && ((!BuffersOrContinuationNowFlag && !ContinuationNextFlag) ||
4467 if(ExitSpeedHalfSquared < 10)
4477 if(ExitSpeedFullSquared < 10)
4540 double DeltaExitTimeToMaxInSecs;
4541 double DistanceToMax;
4550 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4552 DistanceToMax = EntryHalfLength;
4555 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4556 ExitTimeFull =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4573 double DeltaExitTimeToMaxInSecs;
4574 double DistanceToMax;
4583 DeltaExitTimeToMaxInSecs = 2 * EntryHalfLength * 3.6 /
EntrySpeed;
4585 DistanceToMax = EntryHalfLength / 2;
4588 double DeltaRemainingTimeInSecs = 3.6 * RemainingDistance /
MaxExitSpeed;
4589 ExitTimeHalf =
EntryTime + TDateTime((DeltaExitTimeToMaxInSecs + DeltaRemainingTimeInSecs) / 86400.0);
4600 if(ExitSpeedHalfSquared < 10)
4610 if(ExitSpeedFullSquared < 10)
4629 if((EntryPos == 0) || (EntryPos == 2))
4651 if(NextTrackVectorPosition > -1)
4653 int NextElementLength;
4654 if(NextEntryPos > 1)
4662 double NextStoppingSpeed = sqrt(3.6 * 3.6 * 2 *
BrakeRate * NextElementLength);
4849 int ElementCount = 0;
4857 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition;
4875 CurrentTrackVectorPosition).
Attribute != 4))
4915 if((EntryPos == 0) || (EntryPos == 2))
4937 CurrentTrackVectorPosition = NextTrackVectorPosition;
4938 EntryPos = NextEntryPos;
4940 if(ElementCount > 1000)
4968 throw Exception(
"Error - failed to set ReturnVal in ClearToNextSignal()");
4993 bool PlatformFoundFlag =
false, StopRequired =
false, SkipRouteCheck =
false, RouteOrPartRouteSet =
false;
4994 int CurrentTrackVectorPosition =
LeadElement, NextTrackVectorPosition, ElementNumber = 0, Distance = 0;
4995 int RouteStartPosition;
4997 int PlatformPosition;
4999 int EntryPos =
LeadEntryPos, ExitPos, NextEntryPos, RouteID;
5015 if(Distance > (4000 + LeadElementDistance))
5038 if(OtherTrain.
LeadElement == CurrentTrackVectorPosition)
5041 if((OtherCommand ==
"Fjo") || (OtherCommand ==
"jbo") || (OtherCommand ==
"cdt") || (OtherCommand ==
"Frh") ||
5087 if(!PlatformFoundFlag)
5089 PlatformPosition = CurrentTrackVectorPosition;
5092 PlatformFoundFlag =
true;
5108 if((EntryPos == 0) || (EntryPos == 2))
5152 if(ElementNumber < 2)
5154 SkipRouteCheck =
true;
5158 SkipRouteCheck =
false;
5160 if(ElementNumber == 1)
5162 RouteStartPosition = CurrentTrackVectorPosition;
5172 if(ElementNumber > 1)
5176 RouteOrPartRouteSet =
true;
5180 RouteOrPartRouteSet =
false;
5183 if(!SkipRouteCheck && !RouteOrPartRouteSet)
5190 int ExitLink = CurrentTrackElement.
Link[ExitPos];
5191 if((ExitLink == 1) || (ExitLink == 3) || (ExitLink == 7) || (ExitLink == 9))
5203 Distance += CurrentTrackElement.
Length01;
5207 Distance += CurrentTrackElement.
Length23;
5209 NextTrackVectorPosition = CurrentTrackElement.
Conn[ExitPos];
5210 NextEntryPos = CurrentTrackElement.
ConnLinkPos[ExitPos];
5211 CurrentTrackVectorPosition = NextTrackVectorPosition;
5212 EntryPos = NextEntryPos;
5249 return(RepeatHeadCode);
5271 bool FrontValid =
false, RearValid =
false;
5272 TTrackElement FrontAdjacentTrackElement, RearAdjacentTrackElement;
5276 TrainToBeJoinedBy = NULL;
5290 int TrainToBeJoinedByID = -1;
5311 if((TrainToBeJoinedByID < 0) && RearValid)
5330 if(TrainToBeJoinedByID < 0)
5332 TrainToBeJoinedBy = NULL;
5337 if(!TrainToBeJoinedBy->
Stopped())
5339 TrainToBeJoinedBy = NULL;
5349 void TTrain::LogAction(
int Caller, AnsiString OwnHeadCode, AnsiString OtherHeadCode,
TActionType ActionType, AnsiString LocationName, AnsiString SplitDistribution,
5350 TDateTime TimetableNonRepeatTime,
bool Warning)
5386 AnsiString(ActionType) +
"," + LocationName +
"," +
HeadCode);
5387 AnsiString BaseLog =
"", WarningBaseLog =
"", PerfLog =
"", ActionLog =
"";
5388 int IntMinsLate = 0;
5393 ActionLog =
" arrived at ";
5402 ActionLog =
" terminated at ";
5407 ActionLog =
" departed from ";
5409 if(ActionType ==
Pass)
5411 ActionLog =
" passed ";
5415 ActionLog =
" created at ";
5417 if(ActionType ==
Enter)
5419 ActionLog =
" entered railway at ";
5423 ActionLog =
" changed its description to '" +
Description +
"' at ";
5425 if(ActionType ==
Leave)
5427 ActionLog =
" left railway at ";
5431 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from front to ";
5435 ActionLog =
" split mass%-Power% = " + SplitDistribution +
" from rear to ";
5439 ActionLog =
" joined by ";
5443 ActionLog =
" changed direction at ";
5447 ActionLog =
" became new service ";
5451 ActionLog =
" taken under signaller control at ";
5455 ActionLog =
" restored to timetable control at ";
5461 ActionLog =
" REMOVED FROM RAILWAY DUE TO CRASH at ";
5465 ActionLog =
" REMOVED FROM RAILWAY DUE TO DERAILMENT at ";
5469 ActionLog =
" REMOVED FROM RAILWAY at ";
5474 ActionLog =
" received signaller authority to proceed";
5478 ActionLog =
" received signaller authority to step forward";
5482 ActionLog =
" changed direction under signaller control at ";
5486 ActionLog =
" received signaller authority to pass stop signal";
5490 ActionLog =
" received signaller instruction to stop";
5494 ActionLog =
" stopped on signaller instruction ";
5498 ActionLog =
" joined under signaller control by ";
5502 ActionLog =
" suffered an onboard power failure at ";
5506 ActionLog =
" failure repaired at ";
5510 ActionLog =
" left railway under signaller control at ";
5512 if(OtherHeadCode !=
"")
5514 OtherHeadCode +=
" at ";
5527 bool TimePerformance =
true;
5535 TimePerformance =
false;
5539 double MinsLate = ((double)(ActualTime -
GetTrainTime(1, TimetableNonRepeatTime))) * 1440;
5541 if(ActionType ==
Pass)
5555 IntMinsLate = int(ceil(MinsLate));
5559 IntMinsLate = int(floor(MinsLate));
5561 if(IntMinsLate == 0)
5563 PerfLog =
" on time";
5565 else if(IntMinsLate == 1)
5567 PerfLog =
" 1 minute late";
5569 else if(IntMinsLate == -1)
5571 PerfLog =
" 1 minute early";
5573 else if(IntMinsLate > 1)
5575 PerfLog =
" " + AnsiString(IntMinsLate) +
" minutes late";
5577 else if(IntMinsLate < -1)
5579 int PosIntMinsLate = -IntMinsLate;
5580 PerfLog =
" " + AnsiString(PosIntMinsLate) +
" minutes early";
5582 if(LocationName.Pos(
'-') > 0)
5584 PerfLog =
"," + PerfLog;
5598 if((ActionType ==
Arrive) && (IntMinsLate == 0))
5602 else if((ActionType ==
Arrive) && (IntMinsLate > 0))
5607 else if((ActionType ==
Arrive) && (IntMinsLate < 0))
5613 else if((ActionType ==
Pass) && (IntMinsLate == 0))
5617 else if((ActionType ==
Pass) && (IntMinsLate > 0))
5622 else if((ActionType ==
Pass) && (IntMinsLate < 0))
5628 else if((ActionType ==
Leave) && (IntMinsLate == 0))
5632 else if((ActionType ==
Leave) && (IntMinsLate > 0))
5637 else if((ActionType ==
Leave) && (IntMinsLate < 0))
5643 else if((ActionType ==
Depart) && (IntMinsLate == 0))
5647 else if((ActionType ==
Depart) && (IntMinsLate > 0))
5666 AnsiString LocName =
"";
5733 if(LocationName ==
"")
5737 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
5738 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
5739 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
5743 if(LocationName !=
"")
5751 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5756 SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos))
5770 int LeadPosA = FirstNamedElementPos;
5771 int LeadPosB = FirstNamedLinkedElementPos;
5772 int LeadPosC = SecondNamedElementPos;
5773 int LeadPosD = SecondNamedLinkedElementPos;
5775 int LeadNumAtLoc = 0;
5792 if(LeadNumAtLoc < 4)
5796 SecondNamedLinkedElementPos))
5798 FirstNamedElementPos = LeadPosA;
5799 FirstNamedLinkedElementPos = LeadPosB;
5800 SecondNamedElementPos = LeadPosC;
5801 SecondNamedLinkedElementPos = LeadPosD;
5805 int MidNumAtLoc = 0;
5822 if(LeadNumAtLoc > MidNumAtLoc)
5825 FirstNamedElementPos = LeadPosA;
5826 FirstNamedLinkedElementPos = LeadPosB;
5827 SecondNamedElementPos = LeadPosC;
5828 SecondNamedLinkedElementPos = LeadPosD;
5842 throw Exception(
"Error - LocationName not set in FrontTrainSplit");
5852 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5853 FrontTrainRearPosition = FirstNamedElementPos;
5854 RearTrainFrontPosition = SecondNamedElementPos;
5855 RearTrainRearPosition = SecondNamedLinkedElementPos;
5859 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5860 FrontTrainRearPosition = SecondNamedElementPos;
5861 RearTrainFrontPosition = FirstNamedElementPos;
5862 RearTrainRearPosition = FirstNamedLinkedElementPos;
5869 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
5870 FrontTrainRearPosition = SecondNamedElementPos;
5871 RearTrainFrontPosition = FirstNamedElementPos;
5872 RearTrainRearPosition = FirstNamedLinkedElementPos;
5876 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
5877 FrontTrainRearPosition = FirstNamedElementPos;
5878 RearTrainFrontPosition = SecondNamedElementPos;
5879 RearTrainRearPosition = SecondNamedLinkedElementPos;
5882 RearTrainExitPos = -1;
5883 for(
int x = 0; x < 4; x++)
5887 RearTrainExitPos = x;
5891 if(RearTrainExitPos == -1)
5893 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in FrontTrainSplit");
5895 FrontTrainExitPos = -1;
5896 for(
int x = 0; x < 4; x++)
5900 FrontTrainExitPos = x;
5904 if(FrontTrainExitPos == -1)
5906 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in FrontTrainSplit");
5909 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
5916 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
5936 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
5944 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
5945 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
5946 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
5985 double NewTrainPowerAtRail;
5991 NewTrainMass =
Mass * double(MassPercent)/100.0;
5993 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
5994 if(NewTrainPowerAtRail == 0)
5996 NewTrainPowerAtRail = 0.08;
6004 NewTrainMass =
Mass;
6080 if(LocationName ==
"")
6084 int FirstNamedElementPos, SecondNamedElementPos, FirstNamedLinkedElementPos, SecondNamedLinkedElementPos;
6085 int RearTrainRearPosition, RearTrainFrontPosition, RearTrainExitPos;
6086 int FrontTrainRearPosition, FrontTrainFrontPosition, FrontTrainExitPos;
6090 if(LocationName !=
"")
6097 SecondNamedLinkedElementPos))
6101 SecondNamedLinkedElementPos))
6115 int LeadPosA = FirstNamedElementPos;
6116 int LeadPosB = FirstNamedLinkedElementPos;
6117 int LeadPosC = SecondNamedElementPos;
6118 int LeadPosD = SecondNamedLinkedElementPos;
6120 int LeadNumAtLoc = 0;
6137 if(LeadNumAtLoc < 4)
6141 SecondNamedLinkedElementPos))
6143 FirstNamedElementPos = LeadPosA;
6144 FirstNamedLinkedElementPos = LeadPosB;
6145 SecondNamedElementPos = LeadPosC;
6146 SecondNamedLinkedElementPos = LeadPosD;
6150 int MidNumAtLoc = 0;
6167 if(LeadNumAtLoc > MidNumAtLoc)
6170 FirstNamedElementPos = LeadPosA;
6171 FirstNamedLinkedElementPos = LeadPosB;
6172 SecondNamedElementPos = LeadPosC;
6173 SecondNamedLinkedElementPos = LeadPosD;
6187 throw Exception(
"Error - LocationName not set in RearTrainSplit");
6197 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6198 FrontTrainRearPosition = FirstNamedElementPos;
6199 RearTrainFrontPosition = SecondNamedElementPos;
6200 RearTrainRearPosition = SecondNamedLinkedElementPos;
6204 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6205 FrontTrainRearPosition = SecondNamedElementPos;
6206 RearTrainFrontPosition = FirstNamedElementPos;
6207 RearTrainRearPosition = FirstNamedLinkedElementPos;
6214 FrontTrainFrontPosition = SecondNamedLinkedElementPos;
6215 FrontTrainRearPosition = SecondNamedElementPos;
6216 RearTrainFrontPosition = FirstNamedElementPos;
6217 RearTrainRearPosition = FirstNamedLinkedElementPos;
6221 FrontTrainFrontPosition = FirstNamedLinkedElementPos;
6222 FrontTrainRearPosition = FirstNamedElementPos;
6223 RearTrainFrontPosition = SecondNamedElementPos;
6224 RearTrainRearPosition = SecondNamedLinkedElementPos;
6227 RearTrainExitPos = -1;
6228 for(
int x = 0; x < 4; x++)
6232 RearTrainExitPos = x;
6236 if(RearTrainExitPos == -1)
6238 throw Exception(
"Error - RearTrainRearPosition not linked to RearTrainFrontPosition in RearTrainSplit");
6240 FrontTrainExitPos = -1;
6241 for(
int x = 0; x < 4; x++)
6245 FrontTrainExitPos = x;
6249 if(FrontTrainExitPos == -1)
6251 throw Exception(
"Error - FrontTrainRearPosition not linked to FrontTrainFrontPosition in RearTrainSplit");
6254 int TrainIDOnRearOfRearTrain, TrainIDOnFrontOfRearTrain, TrainIDOnRearOfFrontTrain, TrainIDOnFrontOfFrontTrain;
6261 else if((RearMostElement.
TrackType ==
Bridge) && (RearTrainExitPos < 2))
6281 else if((FrontMostElement.
TrackType ==
Bridge) && (FrontTrainExitPos < 2))
6289 if(((TrainIDOnRearOfRearTrain > -1) && (TrainIDOnRearOfRearTrain !=
TrainID)) || ((TrainIDOnFrontOfRearTrain > -1) && (TrainIDOnFrontOfRearTrain !=
TrainID)
6290 ) || ((TrainIDOnRearOfFrontTrain > -1) && (TrainIDOnRearOfFrontTrain !=
TrainID)) ||
6291 ((TrainIDOnFrontOfFrontTrain > -1) && (TrainIDOnFrontOfFrontTrain !=
TrainID)))
6329 double NewTrainPowerAtRail;
6335 NewTrainMass =
Mass * double(MassPercent)/100.0;
6337 NewTrainPowerAtRail =
PowerAtRail * double(PowerPercent)/100.0;
6338 if(NewTrainPowerAtRail == 0)
6340 NewTrainPowerAtRail = 0.08;
6348 NewTrainMass =
Mass;
6470 TTrain *TrainToBeJoinedBy;
6503 double OtherBrakeForce = TrainToBeJoinedBy->
MaxBrakeRate * TrainToBeJoinedBy->
Mass;
6505 double CombinedBrakeRate = (OtherBrakeForce + OwnBrakeForce) / (TrainToBeJoinedBy->
Mass +
Mass);
6566 int RouteNumber = -1;
6571 int CorrectRouteID = OR.
RouteID;
6577 bool FirstPass =
true;
6582 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
6697 for(
int x = 0; x < IncNum; x++)
6730 else if(Ptr->
Command ==
"jbo")
6735 else if(Ptr->
Command ==
"dsc")
6746 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
6752 bool IncludeFER =
false;
6760 if(!IncludeFER && (Ptr->
Command ==
"Fer"))
6765 else if(IncludeFER && (Ptr->
Command ==
"Fer"))
6776 else if(Ptr->
Command ==
"Fjo")
6782 else if(Ptr->
Command ==
"Frh")
6792 else if(Ptr->
Command ==
"Frh-sh")
6843 else if(Ptr->
Command ==
"jbo")
6848 else if(Ptr->
Command ==
"dsc")
6853 else if(Ptr->
Command ==
"cdt")
6861 throw Exception(
"Error - illegal command in SendMissedActionLogs for IncNum = " + AnsiString(IncNum) +
", and command = " + Ptr->
Command);
7272 int RouteNumber = -1;
7277 int CorrectRouteID = OR.
RouteID;
7283 bool FirstPass =
true;
7288 if(FirstPass && (TVPos2 != FirstRouteElementVecPos))
7316 ",FloatingLabelNextString" +
"," +
HeadCode);
7317 AnsiString RetStr =
"", LocationName =
"";
7320 if(ActionTime == TDateTime(-1))
7324 if(ActionTime == TDateTime(-1))
7330 if(ActionTime != TDateTime(-1))
7338 throw Exception(
"Error - start entry in FloatingLabelNextString");
7382 else if(Ptr->
Command ==
"Fns")
7388 else if(Ptr->
Command ==
"F-nshs")
7419 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7421 else if(Ptr->
Command ==
"Frh")
7423 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7425 else if(Ptr->
Command ==
"Fer")
7427 AnsiString AllowedExits =
"";
7430 else if(Ptr->
Command ==
"Fjo")
7435 else if(Ptr->
Command ==
"jbo")
7440 else if(Ptr->
Command ==
"fsp")
7445 else if(Ptr->
Command ==
"rsp")
7450 else if(Ptr->
Command ==
"cdt")
7454 else if(Ptr->
Command ==
"dsc")
7463 throw Exception(
"Error - start entry in FloatingLabelNextString where TTClockTime > ActionTime");
7507 else if(Ptr->
Command ==
"Fns")
7513 else if(Ptr->
Command ==
"F-nshs")
7544 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7546 else if(Ptr->
Command ==
"Frh")
7548 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7550 else if(Ptr->
Command ==
"Fer")
7552 AnsiString AllowedExits =
"";
7555 else if(Ptr->
Command ==
"Fjo")
7560 else if(Ptr->
Command ==
"jbo")
7565 else if(Ptr->
Command ==
"fsp")
7570 else if(Ptr->
Command ==
"rsp")
7575 else if(Ptr->
Command ==
"cdt")
7579 else if(Ptr->
Command ==
"dsc")
7588 throw Exception(
"Error - start entry in FloatingLabelNextString in final 'else'");
7632 else if(Ptr->
Command ==
"Fns")
7638 else if(Ptr->
Command ==
"F-nshs")
7669 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7671 else if(Ptr->
Command ==
"Frh")
7673 RetStr =
"None, train terminated at " + Ptr->
LocationName;
7675 else if(Ptr->
Command ==
"Fer")
7677 AnsiString AllowedExits =
"";
7680 else if(Ptr->
Command ==
"Fjo")
7685 else if(Ptr->
Command ==
"jbo")
7690 else if(Ptr->
Command ==
"fsp")
7695 else if(Ptr->
Command ==
"rsp")
7700 else if(Ptr->
Command ==
"cdt")
7704 else if(Ptr->
Command ==
"dsc")
7848 + AnsiString(RptNum) +
",GetNewServiceDepartureInfo," +
HeadCode);
7849 AnsiString DepTime =
"", EventTime =
"";
7850 bool CDTFlag =
false;
7852 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
7853 AnsiString TowardsLocation =
"";
7856 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
7858 TowardsLocation = AVI->LocationName;
7860 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
7869 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
7876 if(AVI->Command ==
"cdt")
7881 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
7896 RetStr +=
"\nNew service splits at approx. " + EventTime;
7900 if(AVI->Command ==
"jbo")
7915 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at approx. " + EventTime;
7919 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
7934 RetStr +=
"\nNew service finishes and forms another new service at approx. " + EventTime;
7938 if(AVI->Command ==
"Fjo")
7953 RetStr +=
"\nNew service finishes and joins " + AVI->OtherHeadCode +
" at approx. " + EventTime;
7957 if(AVI->Command ==
"Frh")
7959 RetStr +=
"\nNew service finishes and remains at the location.";
7963 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
7970 if(TowardsLocation !=
"")
7972 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
7976 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
7981 if(TowardsLocation !=
"")
7983 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
7987 RetStr +=
"\nNew service departs at " + DepTime;
7996 if(TowardsLocation !=
"")
7998 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
8002 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
8007 if(TowardsLocation !=
"")
8009 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
8013 RetStr +=
"\nNew service departs at approx. " + DepTime;
8030 if(TowardsLocation !=
"")
8032 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at approx. " + DepTime;
8036 RetStr +=
"\nNew service changes direction then departs at approx. " + DepTime;
8041 if(TowardsLocation !=
"")
8043 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at approx. " + DepTime;
8047 RetStr +=
"\nNew service departs at approx. " + DepTime;
8066 ",FloatingTimetableString" +
"," +
HeadCode);
8067 AnsiString RetStr =
"", PartStr =
"";
8069 bool SkipDep =
false, SkipDepActedOn =
false;
8075 throw Exception(
"Error - start entry in FloatingTimetableString");
8078 bool FirstPass =
true;
8091 AnsiString TrainLoc =
"";
8137 AnsiString TrainLoc =
"";
8177 else if(Ptr->
Command ==
"Fns")
8183 else if(Ptr->
Command ==
"F-nshs")
8216 else if(Ptr->
Command ==
"Frh")
8220 else if(Ptr->
Command ==
"Fer")
8222 AnsiString AllowedExits =
"";
8225 else if(Ptr->
Command ==
"Fjo")
8230 else if(Ptr->
Command ==
"jbo")
8235 else if(Ptr->
Command ==
"fsp")
8245 PartStr+=
", split mass%-Power% = 50-50";
8248 else if(Ptr->
Command ==
"rsp")
8258 PartStr+=
", split mass%-Power% = 50-50";
8261 else if(Ptr->
Command ==
"cdt")
8265 else if(Ptr->
Command ==
"dsc")
8271 RetStr = RetStr +
'\n' + PartStr;
8285 SkipDepActedOn =
true;
8296 RetStr =
"Timetable finished";
8300 RetStr =
"No timetable";
8304 return(
"Timetable:\n" + RetStr);
8457 bool ForwardHeadCode;
8461 ForwardHeadCode =
true;
8466 ForwardHeadCode =
false;
8609 if(ColourNumber == 0)
8613 else if(ColourNumber == 1)
8617 else if(ColourNumber == 2)
8621 else if(ColourNumber == 3)
8625 else if(ColourNumber == 4)
8629 else if(ColourNumber == 5)
8633 else if(ColourNumber == 6)
8637 else if(ColourNumber == 7)
8641 else if(ColourNumber == 8)
8645 else if(ColourNumber == 9)
8649 else if(ColourNumber == 10)
8653 else if(ColourNumber == 11)
8657 else if(ColourNumber == 12)
8661 else if(ColourNumber == 13)
8665 else if(ColourNumber == 14)
8677 for(
int x = 0; x < 4; x++)
8684 for(
int x = 0; x < 4; x++)
8769 if((LocationAndMarker[1] !=
'*') && (LocationAndMarker.Length() > 6))
8772 AnsiString Location = LocationAndMarker.SubString(1, LocationAndMarker.Length() - 6);
8773 bool GiveMessagesFalse =
false;
8774 bool CheckLocationsExistInRailwayTrue =
true;
8781 AnsiString Marker = LocationAndMarker.SubString(LocationAndMarker.Length() - 5, 6);
8784 if(Marker[6] ==
'1')
9249 bool HideFlashingTrain =
true;
9252 Graphics::TBitmap *SmallTrainBitmap;
9293 HideFlashingTrain =
false;
9298 HideFlashingTrain =
false;
9303 HideFlashingTrain =
false;
9308 HideFlashingTrain =
false;
9313 HideFlashingTrain =
false;
9317 if((
LeadElement > -1) && (!HideFlashingTrain || Flash))
9321 if((
MidElement > -1) && (!HideFlashingTrain || Flash))
9345 for(
int y = 0; y < 3; y++)
9349 bool FoundFlag =
false;
9360 if(IMPair.first != IMPair.second)
9387 if((LocationName ==
"") && (
MidElement > -1))
9391 if((LocationName ==
"") && (
LagElement > -1))
9395 if(LocationName ==
"")
9397 throw Exception(
"Error - Location name not set in TrainAtLocation");
9408 for(
int x = 0; x < 4; x++)
9420 for(
int x = 0; x < 4; x++)
9437 AnsiString(LinkNumber) +
"," +
HeadCode);
9489 int DistanceToRedSignal = 0, DistanceToExit = -1;
9490 float TimeToAct = 0, LastTimeToExit =
TimeToExit;
9494 float MinsEarly = 0;
9495 TDateTime DepartureTime;
9496 TDateTime ArrivalTime;
9524 if(TempTTE < LastTimeToExit)
9559 if(TempTTE < LastTimeToExit)
9582 if(TempTTE < LastTimeToExit)
9612 if(TempTTE < LastTimeToExit)
9635 if(TempTTE < LastTimeToExit)
9678 float CurrentStopTime;
9679 float LaterStopTime;
9680 float RecoverableTime;
9688 if((DistanceToRedSignal == -1) && (DistanceToExit == -1))
9695 bool DistanceToRedSignalSet = (DistanceToRedSignal > -1);
9696 bool DistanceToExitSet = (DistanceToExit > -1);
9697 int GenericDistance = DistanceToRedSignal;
9698 if(DistanceToExitSet)
9700 GenericDistance = DistanceToExit;
9716 float TimeToSubtract, TotalStopTime;
9719 TimeToSubtract = RecoverableTime;
9762 if(CurrentStopTime > 0)
9764 TotalStopTime = CurrentStopTime + LaterStopTime;
9773 else if((MinsEarly > 0) && !
Stopped())
9775 TotalStopTime = LaterStopTime + MinsEarly;
9779 if(LaterStopTime == 0)
9781 TotalStopTime = CurrentStopTime;
9787 TotalStopTime = CurrentStopTime + LaterStopTime - TimeToSubtract;
9790 if(AvTrackSpeed < 30)
9794 int Speed = AvTrackSpeed;
9804 if(DistanceToRedSignalSet)
9806 TimeToAct = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9816 TimeToExit = TotalStopTime + GenericDistance * 3.6 / 60 / Speed;
9845 if((NextEntryPos == 0) || (NextEntryPos == 2))
9972 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10010 if(AVEntry0.
Command ==
"Snt")
10014 int IncrementalMinutes = 0;
10015 int IncrementalDigits = 0;
10023 throw Exception(
"Error - Repeat entry && less than two trains for Snt entry: " + TDEntry.
HeadCode);
10059 if(AVEntry0.
Command ==
"Snt-sh")
10064 int IncrementalMinutes = 0;
10065 int IncrementalDigits = 0;
10073 throw Exception(
"Error - Repeat entry && less than two trains for Snt-sh entry: " + TDEntry.
HeadCode);
10117 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10197 AnsiString Loc =
"";
10198 bool ElementFound =
false;
10203 ElementFound =
true;
10208 ElementFound =
true;
10213 ElementFound =
true;
10242 else if(AVEntryPtr->
Command ==
"Fer")
10244 bool CorrectExit =
false;
10251 CorrectExit =
true;
10356 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10374 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10389 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10400 bool TTrainController::AddTrain(
int Caller,
int RearPosition,
int FrontPosition, AnsiString HeadCode,
int StartSpeed,
int Mass,
double MaxRunningSpeed,
10401 double MaxBrakeRate,
double PowerAtRail, AnsiString ModeStr,
TTrainDataEntry *TrainDataEntryPtr,
int RepeatNumber,
int IncrementalMinutes,
10402 int IncrementalDigits,
int SignallerSpeed,
bool SignallerControl,
TActionEventType &EventType)
10404 LogEvent(AnsiString(Caller) +
",AddTrain," + AnsiString(RearPosition) +
"," + AnsiString(FrontPosition) +
"," + HeadCode +
"," + AnsiString(StartSpeed) +
10405 "," + AnsiString(Mass) +
"," + ModeStr);
10407 "," + HeadCode +
"," + AnsiString(StartSpeed) +
"," + AnsiString(Mass) +
"," + ModeStr);
10409 int RearExitPos = -1;
10411 for(
int x = 0; x < 4; x++)
10418 if(RearExitPos == -1)
10420 throw Exception(
"Error, RearExit == -1 in AddTrain");
10422 bool ReportFlag =
true;
10427 ReportFlag =
false;
10439 if(ModeStr ==
"Timetable")
10445 if(MaxRunningSpeed < 10)
10447 MaxRunningSpeed = 10;
10449 if(SignallerSpeed < 10)
10451 SignallerSpeed = 10;
10453 TTrain *NewTrain =
new TTrain(0, RearPosition, RearExitPos, HeadCode, StartSpeed, Mass, MaxRunningSpeed, MaxBrakeRate, PowerAtRail, TrainMode,
10454 TrainDataEntryPtr, RepeatNumber, IncrementalMinutes, IncrementalDigits, SignallerSpeed);
10461 if(SignallerControl)
10491 if(!SignallerControl)
10506 if(!SignallerControl)
10517 AnsiString Loc =
"";
10534 if(!SignallerControl)
10553 int RouteNumber = -1;
10554 bool SignalsSet =
false;
10561 int RouteStartPosition;
10565 if(FirstPair.first == RouteNumber)
10567 RouteStartPosition = FirstPair.second;
10569 else if(SecondPair.first == RouteNumber)
10571 RouteStartPosition = SecondPair.second;
10575 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 1st of 2 calls to SetAllRearwardsSignals in AddTrain");
10581 else if(RouteNumber > -1)
10601 int LinkedRouteNumber = -1;
10622 int RouteStartPosition;
10626 if(FirstPair.first == RouteNumber)
10628 RouteStartPosition = FirstPair.second;
10630 else if(SecondPair.first == RouteNumber)
10632 RouteStartPosition = SecondPair.second;
10636 throw Exception(
"Error, RouteNumber not found in Route2MultiMap in 2nd of 2 calls to SetAllRearwardsSignals in AddTrain");
10642 else if(RouteNumber > -1)
10662 int LinkedRouteNumber = -1;
10683 AnsiString(TrackVectorNumber));
10686 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10695 throw Exception(
"Error, VecPos not set in EntryPos");
10697 if(
TrainVectorAt(2, VecPos).LeadElement == TrackVectorNumber)
10702 else if(
TrainVectorAt(4, VecPos).MidElement == TrackVectorNumber)
10707 else if(
TrainVectorAt(6, VecPos).LagElement == TrackVectorNumber)
10721 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10729 throw Exception(
"Error - No Train identified in TrainVectorAtIdent with ID = " + AnsiString(TrainID));
10739 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
10760 return(RepeatTime);
10769 AnsiString RetStr =
"", PartStr =
"";
10777 if((Ptr->Command !=
"") && (Ptr->Command[1] ==
'S'))
10785 if(Ptr->SignallerControl)
10787 RetStr =
"Train under signaller control";
10792 if(Ptr->ArrivalTime == Ptr->DepartureTime)
10803 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime != TDateTime(-1)))
10807 else if((Ptr->FormatType ==
TimeLoc) && (Ptr->ArrivalTime == TDateTime(-1)))
10811 else if(Ptr->FormatType ==
PassTime)
10815 else if(Ptr->Command ==
"Fns")
10821 else if(Ptr->Command ==
"F-nshs")
10824 Ptr->NonRepeatingShuttleLinkHeadCode +
" at " + Ptr->LocationName;
10831 else if((Ptr->Command ==
"Fns-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10838 else if((Ptr->Command ==
"Fns-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10841 Ptr->NonRepeatingShuttleLinkHeadCode, +
" at " + Ptr->LocationName;
10844 else if((Ptr->Command ==
"Frh-sh") && (RepNum < (TTDEPtr->
NumberOfTrains - 1)))
10851 else if((Ptr->Command ==
"Frh-sh") && (RepNum >= (TTDEPtr->
NumberOfTrains - 1)))
10853 PartStr =
"Terminate at " + Ptr->LocationName;
10855 else if(Ptr->Command ==
"Frh")
10857 PartStr =
"Terminate at " + Ptr->LocationName;
10859 else if(Ptr->Command ==
"Fer")
10861 AnsiString AllowedExits;
10865 else if(Ptr->Command ==
"Fjo")
10868 Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10870 else if(Ptr->Command ==
"jbo")
10873 (50, Ptr->OtherHeadCode, RepNum, IncDig) +
" at " + Ptr->LocationName;
10875 else if(Ptr->Command ==
"fsp")
10880 else if(Ptr->Command ==
"rsp")
10885 else if(Ptr->Command ==
"cdt")
10889 else if(Ptr->Command ==
"dsc")
10895 RetStr = RetStr +
'\n' + PartStr;
10903 while(Ptr < TTDEPtr->ActionVector.end() && (Count < 33) && ((Ptr->Command ==
"") || ((Ptr->Command !=
"") && (Ptr->Command[1] !=
'F'))));
10916 + AnsiString(RptNum) +
",ControllerGetNewServiceDepartureInfo," + TDEPtr->
HeadCode);
10917 AnsiString DepTime =
"", EventTime =
"";
10918 bool CDTFlag =
false;
10920 AnsiString CurrentLocation = NewServiceAV.at(0).LocationName;
10921 AnsiString TowardsLocation =
"";
10924 if((AVI->LocationName != CurrentLocation) && (AVI->LocationName !=
"") && (TowardsLocation ==
""))
10926 TowardsLocation = AVI->LocationName;
10928 else if((AVI->Command ==
"Fer") && (TowardsLocation ==
"") && !AVI->ExitList.empty())
10937 TowardsLocation = AnsiString(
"track element ID ") + TE.
ElementID;
10943 if(AVI->Command ==
"cdt")
10945 CDTFlag = !CDTFlag;
10948 if((AVI->Command ==
"fsp") || (AVI->Command ==
"rsp"))
10951 RetStr +=
"\nNew service splits at " + EventTime;
10955 if(AVI->Command ==
"jbo")
10958 RetStr +=
"\nNew service joined by " + AVI->OtherHeadCode +
" at " + EventTime;
10962 if((AVI->Command ==
"Fns") || (AVI->Command ==
"F-nshs") || (AVI->Command ==
"Fns-sh"))
10965 RetStr +=
"\nNew service finishes and forms another new service at " + EventTime;
10969 if(AVI->Command ==
"Fjo")
10972 RetStr +=
"\nNew service finishes and joins " + AVI->OtherHeadCode +
" at " + EventTime;
10976 if(AVI->Command ==
"Frh")
10978 RetStr +=
"\nNew service finishes and remains at location.";
10982 if((AVI->FormatType ==
TimeLoc) && (AVI->DepartureTime > TDateTime(-1)))
10987 if(TowardsLocation !=
"")
10989 RetStr +=
"\nNew service changes direction then departs towards " + TowardsLocation +
" at " + DepTime;
10993 RetStr +=
"\nNew service changes direction then departs at " + DepTime;
10998 if(TowardsLocation !=
"")
11000 RetStr +=
"\nNew service departs towards " + TowardsLocation +
" at " + DepTime;
11004 RetStr +=
"\nNew service departs at " + DepTime;
11169 ActiveTrackElementNameMapEntry.second = 0;
11175 std::ifstream TTBLFile(FileName, std::ios_base::binary);
11178 if(TTBLFile.is_open())
11180 char *TrainTimetableString =
new char[10000];
11182 bool EndOfFile =
false;
11185 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11187 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11194 delete[] TrainTimetableString;
11198 AnsiString OneLine(TrainTimetableString);
11199 bool FinalCallFalse =
false;
11200 while((Count == 0) && !
ProcessOneTimetableLine(5, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11204 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11205 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11210 TimetableMessage(GiveMessages,
"Timetable invalid - unable to find a valid start time on its own line");
11212 delete[] TrainTimetableString;
11216 OneLine = AnsiString(TrainTimetableString);
11222 TTBLFile.getline(TrainTimetableString, 10000,
'\0');
11224 if(TTBLFile.eof() && (TrainTimetableString[0] ==
'\0'))
11234 OneLine = AnsiString(TrainTimetableString);
11236 if(OneLine.Length() > 9999)
11238 TimetableMessage(GiveMessages,
"Timetable contains a line that is too long - 10,000 or more characters!");
11240 delete[] TrainTimetableString;
11244 bool FinalCallFalse =
false;
11245 if(!
ProcessOneTimetableLine(6, Count, OneLine, EndOfFile, FinalCallFalse, GiveMessages, CheckLocationsExistInRailway))
11249 delete[] TrainTimetableString;
11253 if(EndOfFile && (Count < 2))
11256 TimetableMessage(GiveMessages,
"Timetable has too few or no relevant entries - must have a start time on its own line and at least one train");
11258 delete[] TrainTimetableString;
11264 delete[] TrainTimetableString;
11269 TimetableMessage(GiveMessages,
"Failed to open timetable file, make sure it's spelled correctly, it exists and isn't open in another application");
11280 bool CheckLocationsExistInRailway)
11408 AnsiString((
short)FinalCall) +
"," + AnsiString((
short)CheckLocationsExistInRailway));
11418 if(OneLine[1] !=
'*')
11420 int SCPos = OneLine.Pos(
';');
11431 bool AllCommas =
true;
11433 for(
int x = 1; x < OneLine.Length() + 1; x++)
11435 if(OneLine[x] !=
',')
11440 if(AllCommas || (OneLine ==
""))
11455 AnsiString First =
"", Second =
"", Third =
"", Fourth =
"";
11456 int RearStartOrRepeatMins = 0, FrontStartOrRepeatDigits = 0, NumberOfRepeats = 0;
11457 TDateTime EventTime(0), ArrivalTime(0), DepartureTime(0);
11458 TDateTime StartTime(0);
11460 bool Warning =
false;
11487 AnsiString TrainInfoStr =
"", HeadCode =
"", Description =
"";
11488 int StartSpeed = 0, MaxRunningSpeed = 0, Mass = 0;
11489 double MaxBrakeRate = 0;
11490 double PowerAtRail = 0;
11491 int SignallerSpeed = 0;
11492 if(OneLine[1] ==
'*')
11498 int Pos = OneLine.Pos(
',');
11501 int SubStringLength = 20;
11502 if(OneLine.Length() < 20)
11504 SubStringLength = OneLine.Length();
11506 TimetableMessage(GiveMessages,
"Error in timetable - entry incomplete: see '" + OneLine.SubString(1, SubStringLength) +
"'....");
11510 TrainInfoStr = OneLine.SubString(1, Pos - 1);
11511 if(!
SplitTrainInfo(0, TrainInfoStr, HeadCode, Description, StartSpeed, MaxRunningSpeed, Mass, MaxBrakeRate, PowerAtRail, SignallerSpeed,
11522 TempTrainDataEntry.
HeadCode = HeadCode;
11526 if(Description !=
"")
11531 TempTrainDataEntry.
Mass = Mass;
11539 AnsiString NewRemainder = OneLine.SubString(Pos + 1, OneLine.Length() - Pos);
11542 while(NewRemainder[NewRemainder.Length()] ==
',')
11544 if(NewRemainder.Length() > 1)
11546 NewRemainder = NewRemainder.SubString(1, NewRemainder.Length() - 1);
11555 if(NewRemainder ==
"")
11557 TimetableMessage(GiveMessages,
"Error in timetable - no events following train: '" + OneLine +
"'");
11562 int CommaCount = 0;
11563 for(
int x = 1; x < NewRemainder.Length() + 1; x++)
11565 if(NewRemainder[x] ==
',')
11570 if(CommaCount == 0)
11572 if((NewRemainder.SubString(7, 3) !=
"Snt") || (NewRemainder[NewRemainder.Length()] !=
'S'))
11574 int SubStringLength = 20;
11575 if(OneLine.Length() < 20)
11577 SubStringLength = OneLine.Length();
11580 "Error in timetable - must have at least a start and a finish event for a train that is not started under signaller control - see line beginning: '" +
11581 OneLine.SubString(1, SubStringLength) +
"'....");
11586 AnsiString OneEntry =
"";
11591 bool FinishFlag =
false;
11592 bool NewTrain =
false;
11593 for(
int x = 0; x < CommaCount + 1; x++)
11595 if((CommaCount == 0) || (x < CommaCount))
11600 if(CommaCount == 0)
11602 OneEntry = NewRemainder;
11607 Pos = NewRemainder.Pos(
',');
11608 OneEntry = NewRemainder.SubString(1, Pos - 1);
11609 NewRemainder = NewRemainder.SubString(Pos + 1, NewRemainder.Length() - Pos);
11615 RearStartOrRepeatMins = 0;
11616 FrontStartOrRepeatDigits = 0;
11617 NumberOfRepeats = 0;
11618 if(!
SplitEntry(0, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11619 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11621 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11625 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11630 if(Warning && (Second ==
"Frh"))
11632 TimetableMessage(GiveMessages,
"Error in line - '" + OneEntry +
"': warnings cannot be given for 'Frh' events");
11636 if(Warning && (Second ==
"Fjo"))
11639 "': warnings cannot be given for 'Fjo' events, for a train join warning add a 'W' prefix to the 'jbo' event");
11645 if(NewTrain && (PowerAtRail < 1) && (Second ==
"jbo"))
11648 "': a train created without power can't 'be joined by' another train (i.e. can't include command 'jbo'), "
11649 "use command 'Fjo' (i.e. 'join' another train) instead immediately after the line containing 'Snt', and use "
11650 "command 'jbo' for the train it is to join.");
11654 if(NewTrain && (PowerAtRail < 1) && ((Second ==
"fsp") || (Second ==
"rsp")))
11657 "': a train created without power can't split.");
11661 if(NewTrain && (PowerAtRail < 1) && (Second ==
"cdt"))
11664 "': a train created without power can't change direction under timetable control.");
11673 TimetableMessage(GiveMessages,
"Error in timetable - First event not a start event: '" + OneEntry +
"'");
11677 if((Second ==
"Snt") && (Fourth ==
'S') && (NewRemainder !=
""))
11679 if(NewRemainder[1] !=
'R')
11682 "Error in timetable - the only event that can follow a train created under signaller control is a repeat, see '" +
11688 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
11692 if((HeadCode ==
"") || (Description ==
"") || (MaxRunningSpeed == 0) || (Mass == 0) || (MaxBrakeRate == 0))
11695 TimetableMessage(GiveMessages,
"Error in timetable - train information incomplete before 'Snt' or 'Snt-sh' start event: '" +
11701 if((Second ==
"Sfs") || (Second ==
"Sns") || (Second ==
"Sns-sh") || (Second ==
"Sns-fsh"))
11706 TimetableMessage(GiveMessages,
"Error in timetable - headcode missing before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11711 if((StartSpeed != 0) || (MaxRunningSpeed != 0) || (Mass != 0) || (MaxBrakeRate != 0) || (PowerAtRail != 0))
11714 "Error in timetable - information additional to a headcode & optional description given before 'Sfs', 'Sns', 'Sns-sh' or 'Sns-fsh' start event: '" +
11730 TDateTime TempTime;
11736 ActionVectorEntry.
Warning = Warning;
11752 ActionVectorEntry.
Command = Second;
11767 else if(FormatType ==
TimeCmd)
11773 ActionVectorEntry.
Command = Second;
11781 ActionVectorEntry.
Command = Second;
11782 ActionVectorEntry.
ExitList = ExitList;
11790 ActionVectorEntry.
Command = Second;
11804 ActionVectorEntry.
Command = Second;
11815 ActionVectorEntry.
Command = Second;
11825 ActionVectorEntry.
Command = Second;
11827 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
11838 ActionVectorEntry.
Command = Second;
11847 ActionVectorEntry.
Command = Second;
11853 ActionVectorEntry.
Command = Second;
11861 ActionVectorEntry.
Command = Second;
11864 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11869 OneEntry = NewRemainder;
11874 RearStartOrRepeatMins = 0;
11875 FrontStartOrRepeatDigits = 0;
11876 NumberOfRepeats = 0;
11877 if((FinishFlag) && (OneEntry[1] !=
'R'))
11880 TimetableMessage(GiveMessages,
"Error in timetable - Last event = '" + OneEntry +
"'. An earlier finish event has been found with something other than a repeat following it - only a repeat can follow a finish event.");
11884 if(OneEntry[1] !=
'R')
11886 if(!
SplitEntry(1, OneEntry, GiveMessages, CheckLocationsExistInRailway, First, Second, Third, Fourth, RearStartOrRepeatMins,
11887 FrontStartOrRepeatDigits, FormatType, LocationType, SequenceType, ShuttleLinkType, ExitList, Warning))
11889 TimetableMessage(GiveMessages,
"Error in timetable - Event: '" + OneEntry +
"'");
11894 if(NewTrain && (PowerAtRail < 1) && ((Second ==
"Fns") || (Second ==
"Frh-sh") || (Second ==
"Fns-sh") || (Second ==
"F-nshs")))
11897 "': a train created without power can't form a new service.");
11904 TimetableMessage(GiveMessages,
"Error in timetable - last event should be a finish: '" + OneEntry +
"'");
11911 TDateTime TempTime;
11917 ActionVectorEntry.
Warning = Warning;
11924 ActionVectorEntry.
Command = Second;
11932 ActionVectorEntry.
Command = Second;
11941 ActionVectorEntry.
Command = Second;
11950 ActionVectorEntry.
Command = Second;
11960 ActionVectorEntry.
Command = Second;
11961 ActionVectorEntry.
ExitList = ExitList;
11965 ActionVectorEntry.
Command = Second;
11967 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
11972 if(!
SplitRepeat(0, OneEntry, RearStartOrRepeatMins, FrontStartOrRepeatDigits, NumberOfRepeats, GiveMessages))
11988 TempTrainDataEntry.
ActionVector.push_back(ActionVectorEntry);
12007 if((HeadCode[HeadCode.Length() - 1] <
'0') || (HeadCode[HeadCode.Length() - 1] >
'9'))
12012 if((HeadCode[HeadCode.Length()] <
'0') || (HeadCode[HeadCode.Length()] >
'9'))
12027 if(TimeStr.Length() < 5)
12032 if((TimeStr[1] <
'0') || (TimeStr[1] >
'9'))
12037 if((TimeStr[2] <
'0') || (TimeStr[2] >
'9'))
12042 if(TimeStr[3] !=
':')
12047 if((TimeStr[4] <
'0') || (TimeStr[4] >
'5'))
12052 if((TimeStr[5] <
'0') || (TimeStr[5] >
'9'))
12057 while(TimeStr.Length() > 5)
12059 TimeStr = TimeStr.SubString(1, TimeStr.Length() - 1);
12061 double WholeHours = (AnsiString(TimeStr[1]) + AnsiString(TimeStr[2])).ToDouble();
12062 double FracHour = ((AnsiString(TimeStr[4]) + AnsiString(TimeStr[5])).ToDouble()) / 60.0;
12064 if((WholeHours + FracHour) >= 95.98334)
12069 Time = TDateTime((WholeHours + FracHour) / 24);
12076 bool TTrainController::SplitEntry(
int Caller, AnsiString OneEntry,
bool GiveMessages,
bool CheckLocationsExistInRailway, AnsiString &First, AnsiString &Second,
12077 AnsiString &Third, AnsiString &Fourth,
int &RearStartOrRepeatMins,
int &FrontStartOrRepeatDigits,
TTimetableFormatType &FormatType,
12086 TDateTime TempTime;
12088 if(OneEntry.Length() > 0)
12090 if(OneEntry[1] ==
'W')
12093 OneEntry = OneEntry.SubString(2, OneEntry.Length() - 1);
12097 if(OneEntry ==
"Frh")
12107 if(OneEntry.Length() < 7)
12112 int Pos = OneEntry.Pos(
';');
12120 First = OneEntry.SubString(1, 5);
12126 AnsiString Remainder = OneEntry.SubString(Pos + 1, OneEntry.Length() - Pos);
12129 if((Remainder.Length() >= 3) && (Remainder[1] >=
'0') && (Remainder[1] <=
'9') && (Remainder[2] >=
'0') && (Remainder[2] <=
'9') && (Remainder[3] ==
':'))
12132 if(Remainder.Length() < 7)
12137 Pos = Remainder.Pos(
';');
12144 Second = Remainder.SubString(1, 5);
12150 Third = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12163 Pos = Remainder.Pos(
';');
12166 Second = Remainder;
12167 if(Second ==
"cdt")
12192 if((Pos != 4) && (Pos != 7) && (Pos != 8))
12198 Second = Remainder.SubString(1, Pos - 1);
12200 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12202 Pos = Remainder.Pos(
';');
12209 Third = Remainder.SubString(1, Pos - 1);
12210 Fourth = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12213 if((Second ==
"Snt") || (Second ==
"Snt-sh"))
12216 int SpacePos = Third.Pos(
' ');
12222 AnsiString RearStartStr = Third.SubString(1, SpacePos - 1);
12223 AnsiString FrontStartStr = Third.SubString(SpacePos + 1, Third.Length() - SpacePos);
12225 if(CheckLocationsExistInRailway)
12235 if(Second ==
"Snt")
12258 if(Second ==
"Sns-sh")
12277 if(Second ==
"F-nshs")
12291 if(Second ==
"Sns-fsh")
12305 if(Second ==
"Fns-sh")
12325 if(Second ==
"pas")
12340 if(Second ==
"Fer")
12347 if(CheckLocationsExistInRailway)
12358 if(Second ==
"dsc")
12360 if(Third.Length() > 60)
12362 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters in '" + Third +
"'");
12366 for(
int x = 1; x < Third.Length() + 1; x++)
12369 if((Third[x] <
' ') && (Third[x] >= 0))
12371 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + Third +
"'");
12387 if((Second !=
"Fns") && (Second !=
"Fjo") && (Second !=
"jbo") && (Second !=
"fsp") && (Second !=
"rsp") && (Second !=
"Sfs") && (Second !=
"Sns") &&
12388 (Second !=
"Frh-sh"))
12400 if(Second ==
"Frh-sh")
12408 if((Second ==
"Fns") || (Second ==
"Fjo") || (Second ==
"Frh-sh"))
12412 if((Second ==
"jbo") || (Second ==
"fsp") || (Second ==
"rsp"))
12416 if((Second ==
"Sfs") || (Second ==
"Sns"))
12421 if((Fourth !=
"") && ((Second ==
"fsp") || (Second ==
"rsp")))
12438 bool ErrorFlag =
false;
12440 if((SplitDistributionString.Length() > 6 ) || (SplitDistributionString.Length() < 3))
12444 int pos = SplitDistributionString.Pos(
'-');
12451 AnsiString MassStr = SplitDistributionString.SubString(1, pos - 1);
12452 AnsiString PowerStr = SplitDistributionString.SubString(pos + 1, SplitDistributionString.Length() - pos);
12455 int x = MassStr.ToInt();
12456 int y = PowerStr.ToInt();
12457 if((x > 99) || (x < 1) || (y > 100) || (y < 0))
12462 catch(
const Exception &e)
12469 TimetableMessage(GiveMessages,
"Error in split distribution " + SplitDistributionString +
", should be 'AA-BB' where AA is the percentage mass (min 1, max 99) and BB the percentage " +
12470 "power for the new split-off train");
12491 if((LocStr.Length() >= 3) && (LocStr[1] >=
'0') && (LocStr[1] <=
'9') && (LocStr[2] >=
'0') && (LocStr[2] <=
'9') && (LocStr[3] ==
':'))
12496 for(
int x = 1; x < LocStr.Length() + 1; x++)
12498 if(((LocStr[x] <
' ') && (LocStr[x] >= 0)) || (LocStr[x] ==
',') || (LocStr[x] ==
';'))
12512 if(CheckLocationsExistInRailway)
12517 "' appears in the timetable but is not a valid name. To be valid the name must be a stopping location and apply to one or more platforms " +
12518 "(not concourses on their own), or to track at a blue non-station named location. BUT NOTE THAT trains can't stop at continuations so a name " +
12519 "that includes a continuation will not be valid.");
12537 if((HeadCode.Length() < 4) || (HeadCode.Length() > 8))
12540 "', length must be between 4 and 8 characters, and last 4 must be a legitimate headcode. This error can also be caused by omitting a service reference after Sns, Snt-sh, Sns-sh, Fns, Fns-sh or Frh-sh");
12545 for(
int x = 1; x < (HeadCode.Length() + 1); x++)
12547 if((HeadCode[x] <
' ') || (HeadCode[x] >
'~'))
12549 TimetableMessage(GiveMessages,
"Non-printable character in headcode '" + HeadCode +
"'");
12555 for(
int x = 3; x >= 0; x--)
12557 if(((HeadCode[HeadCode.Length() - x] <
'A') || (HeadCode[HeadCode.Length() - x] >
'Z')) && ((HeadCode[HeadCode.Length() - x] <
'a') ||
12558 (HeadCode[HeadCode.Length() - x] >
'z')) && ((HeadCode[HeadCode.Length() - x] <
'0') || (HeadCode[HeadCode.Length() - x] >
'9')))
12560 TimetableMessage(GiveMessages,
"Headcode error in '" + HeadCode +
"', headcode must consist of letters and digits only");
12576 AnsiString CurrentID =
"";
12578 if(IDSet.Length() == 0)
12580 TimetableMessage(GiveMessages,
"Must have at least one exit element ID following 'Fer'");
12584 for(
int x = 1; x <= IDSet.Length(); x++)
12587 if(((C <
'0') || (C >
'9')) && (C !=
' ') && (C !=
'N') && (C !=
'-'))
12589 TimetableMessage(GiveMessages,
"Illegal character in the set of element IDs following 'Fer' in '" + IDSet +
"'");
12611 int Pos = IDSet.Pos(
' ');
12622 CurrentID = IDSet.SubString(1, Pos - 1);
12623 IDSet = IDSet.SubString(Pos + 1, IDSet.Length() - Pos);
12635 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' is not an exit");
12642 if(!ExitList.empty())
12644 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
12646 if(*ELIT == VecPos)
12648 TimetableMessage(GiveMessages,
"The element ID '" + CurrentID +
"' following 'Fer' duplicates an earlier element");
12655 ExitList.push_back(VecPos);
12665 Pos = IDSet.Pos(
' ');
12672 int &Mass,
double &MaxBrakeRate,
double &PowerAtRail,
int &SignallerSpeed,
bool GiveMessages)
12679 AnsiString Remainder =
"";
12680 int SemiColonCount = 0;
12682 for(
int x = 1; x < TrainInfoStr.Length() + 1; x++)
12684 if(TrainInfoStr[x] ==
';')
12689 if((SemiColonCount != 6) && (SemiColonCount != 7) && (SemiColonCount != 1) && (SemiColonCount != 0))
12691 TimetableMessage(GiveMessages,
"Error in train information in '" + TrainInfoStr +
12692 "'. Should be headcode + optional description for a continuing service;" +
12693 " or headcode, description, start speed, max running speed, mass, brake force, power (and optional signaller max. speed) for a new service");
12697 if(SemiColonCount == 0)
12699 HeadCode = TrainInfoStr;
12708 if(SemiColonCount == 1)
12710 Pos = TrainInfoStr.Pos(
';');
12711 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12712 Description = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12718 if(Description ==
"")
12720 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12724 if(Description.Length() > 60)
12726 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12730 for(
int x = 1; x < Description.Length() + 1; x++)
12733 if((Description[x] <
' ') && (Description[x] >= 0))
12735 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12744 Pos = TrainInfoStr.Pos(
';');
12745 HeadCode = TrainInfoStr.SubString(1, Pos - 1);
12746 Remainder = TrainInfoStr.SubString(Pos + 1, TrainInfoStr.Length() - Pos);
12752 Pos = Remainder.Pos(
';');
12753 Description = Remainder.SubString(1, Pos - 1);
12754 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12755 if(Description ==
"")
12757 TimetableMessage(GiveMessages,
"Train description missing in '" + TrainInfoStr +
"'");
12761 if(Description.Length() > 60)
12763 TimetableMessage(GiveMessages,
"Train description too long, limit of 60 characters '" + TrainInfoStr +
"'");
12767 for(
int x = 1; x < Description.Length() + 1; x++)
12770 if((Description[x] <
' ') && (Description[x] >= 0))
12772 TimetableMessage(GiveMessages,
"Train description contains invalid characters in '" + TrainInfoStr +
"'");
12777 Pos = Remainder.Pos(
';');
12778 AnsiString StartSpeedStr = Remainder.SubString(1, Pos - 1);
12780 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12781 if(StartSpeedStr ==
"")
12783 TimetableMessage(GiveMessages,
"Train starting speed missing in '" + TrainInfoStr +
"'");
12787 for(
int x = 1; x < StartSpeedStr.Length() + 1; x++)
12789 if((StartSpeedStr[x] <
'0') || (StartSpeedStr[x] >
'9'))
12791 TimetableMessage(GiveMessages,
"Train start speed contains invalid characters in '" + TrainInfoStr +
"'");
12796 StartSpeed = StartSpeedStr.ToInt();
12802 TimetableMessage(GiveMessages,
"Train starting speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12806 Pos = Remainder.Pos(
';');
12807 AnsiString MaxRunningSpeedStr = Remainder.SubString(1, Pos - 1);
12809 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12810 if(MaxRunningSpeedStr ==
"")
12812 TimetableMessage(GiveMessages,
"Train maximum running speed missing in '" + TrainInfoStr +
"'");
12816 for(
int x = 1; x < MaxRunningSpeedStr.Length() + 1; x++)
12818 if((MaxRunningSpeedStr[x] <
'0') || (MaxRunningSpeedStr[x] >
'9'))
12820 TimetableMessage(GiveMessages,
"Train maximum running speed contains invalid characters in '" + TrainInfoStr +
"'");
12825 MaxRunningSpeed = MaxRunningSpeedStr.ToInt();
12831 TimetableMessage(GiveMessages,
"Train maximum running speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
12835 if(MaxRunningSpeed < 10)
12838 MaxRunningSpeed = 10;
12841 TimetableMessage(GiveMessages,
"Train maximum running speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
12845 Pos = Remainder.Pos(
';');
12846 AnsiString MassStr = Remainder.SubString(1, Pos - 1);
12848 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12851 TimetableMessage(GiveMessages,
"Train mass missing in '" + TrainInfoStr +
"'");
12855 for(
int x = 1; x < MassStr.Length() + 1; x++)
12857 if((MassStr[x] <
'0') || (MassStr[x] >
'9'))
12859 TimetableMessage(GiveMessages,
"Train mass contains invalid characters in '" + TrainInfoStr +
"'");
12864 Mass = MassStr.ToInt() * 1000;
12870 TimetableMessage(GiveMessages,
"Train mass > 10,000 tonnes in '" + TrainInfoStr +
"'. Setting it to 10,000 tonnes");
12876 TimetableMessage(GiveMessages,
"Train mass zero in '" + TrainInfoStr +
"'");
12880 Pos = Remainder.Pos(
';');
12881 AnsiString MaxBrakeForceStr = Remainder.SubString(1, Pos - 1);
12883 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12884 if(MaxBrakeForceStr ==
"")
12886 TimetableMessage(GiveMessages,
"Train braking force missing in '" + TrainInfoStr +
"'");
12890 for(
int x = 1; x < (MaxBrakeForceStr.Length() + 1); x++)
12892 if((MaxBrakeForceStr[x] !=
'.') && ((MaxBrakeForceStr[x] <
'0') || (MaxBrakeForceStr[x] >
'9')))
12894 TimetableMessage(GiveMessages,
"Train braking force contains invalid characters in '" + TrainInfoStr +
"'");
12899 double MaxBrakeForce = MaxBrakeForceStr.ToDouble() * 1000;
12902 if((MaxBrakeForce / Mass) > 1)
12904 MaxBrakeForce = Mass;
12907 TimetableMessage(GiveMessages,
"Train braking force too high in '" + TrainInfoStr +
"'. Setting it to the same as the train mass");
12911 if((MaxBrakeForce / Mass) < 0.01)
12913 MaxBrakeForce = Mass * 0.01;
12916 TimetableMessage(GiveMessages,
"Train braking force too low in '" + TrainInfoStr +
"'. Setting it to 1% of the train mass");
12921 MaxBrakeRate = MaxBrakeForce / Mass * 9.81;
12923 AnsiString GrossPowerStr =
"", SignallerSpeedStr =
"";
12925 if(SemiColonCount == 6)
12927 GrossPowerStr = Remainder;
12928 SignallerSpeedStr =
"30";
12932 Pos = Remainder.Pos(
';');
12933 GrossPowerStr = Remainder.SubString(1, Pos - 1);
12934 SignallerSpeedStr = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
12937 if(GrossPowerStr ==
"")
12939 TimetableMessage(GiveMessages,
"Train power missing in '" + TrainInfoStr +
"'");
12943 for(
int x = 1; x < GrossPowerStr.Length() + 1; x++)
12945 if((GrossPowerStr[x] <
'0') || (GrossPowerStr[x] >
'9'))
12947 TimetableMessage(GiveMessages,
"Train power contains invalid characters in '" + TrainInfoStr +
"'");
12953 double GrossPower = GrossPowerStr.ToInt() * 1000;
12960 TimetableMessage(GiveMessages,
"Train power > 100,000kW in '" + TrainInfoStr +
"'. Setting it to 100,000kW");
12964 else if(GrossPower == 0)
12969 else if((GrossPower > 0) && (GrossPower < 10000))
12972 GrossPower = 10000;
12974 PowerAtRail = GrossPower * 0.8;
12978 if(SignallerSpeedStr ==
"")
12980 TimetableMessage(GiveMessages,
"Signaller speed not set in '" + TrainInfoStr +
"', either set a value or remove the extra semicolon");
12984 for(
int x = 1; x < SignallerSpeedStr.Length() + 1; x++)
12986 if((SignallerSpeedStr[x] <
'0') || (SignallerSpeedStr[x] >
'9'))
12988 TimetableMessage(GiveMessages,
"Signaller speed contains invalid characters in '" + TrainInfoStr +
"'");
12993 SignallerSpeed = SignallerSpeedStr.ToInt();
12999 TimetableMessage(GiveMessages,
"Signaller speed > 400km/h in '" + TrainInfoStr +
"'. Setting it to 400km/h");
13003 if(SignallerSpeed < 10)
13006 SignallerSpeed = 10;
13009 TimetableMessage(GiveMessages,
"Signaller speed can't be less than 10km/h in '" + TrainInfoStr +
"', it will be set to 10km/h");
13027 if(OneEntry.Length() < 7)
13029 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13033 int SemiColonCount = 0;
13035 for(
int x = 1; x < OneEntry.Length() + 1; x++)
13037 if(OneEntry[x] ==
';')
13042 if(SemiColonCount != 3)
13044 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13048 if((OneEntry[1] !=
'R') || (OneEntry[2] !=
';'))
13050 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - should be 'R;m;d;n'");
13054 AnsiString Remainder = OneEntry.SubString(3, OneEntry.Length() - 2);
13059 Pos = Remainder.Pos(
';');
13060 AnsiString MinutesStr = Remainder.SubString(1, Pos - 1);
13062 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13063 if(MinutesStr ==
"")
13065 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute increment segment missing");
13069 if(MinutesStr.Length() > 3)
13072 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - minute value too high, maximum value is 999");
13076 for(
int x = 1; x < MinutesStr.Length() + 1; x++)
13078 if((MinutesStr[x] <
'0') || (MinutesStr[x] >
'9'))
13080 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in minute increment segment");
13085 RearStartOrRepeatMins = MinutesStr.ToInt();
13086 if(RearStartOrRepeatMins == 0)
13088 TimetableMessage(GiveMessages,
"Repeat minute increment is zero in: '" + OneEntry +
"' - can't have a zero value");
13092 Pos = Remainder.Pos(
';');
13093 AnsiString DigitsStr = Remainder.SubString(1, Pos - 1);
13095 Remainder = Remainder.SubString(Pos + 1, Remainder.Length() - Pos);
13096 if(DigitsStr ==
"")
13098 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - headcode increment segment missing");
13102 for(
int x = 1; x < DigitsStr.Length() + 1; x++)
13104 if((DigitsStr[x] <
'0') || (DigitsStr[x] >
'9'))
13106 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in headcode increment segment");
13111 if(DigitsStr.Length() > 2)
13113 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - maximum number of digits for headcode increment is 2");
13117 FrontStartOrRepeatDigits = DigitsStr.ToInt();
13131 "' - a repeating service with incrementing digits must have digits as its last two headcode characters");
13135 AnsiString NumberStr = Remainder;
13137 if(NumberStr ==
"")
13139 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - number of repeats missing");
13143 if(NumberStr.Length() > 4)
13146 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - repeat value too high, no timetabled event can exceed 95 hours & 59 minutes");
13150 for(
int x = 1; x < NumberStr.Length() + 1; x++)
13152 if((NumberStr[x] <
'0') || (NumberStr[x] >
'9'))
13155 TimetableMessage(GiveMessages,
"Error in repeat: '" + OneEntry +
"' - non-digit character in number of repeats");
13160 NumberOfRepeats = NumberStr.ToInt();
13161 if(NumberOfRepeats == 0)
13163 TimetableMessage(GiveMessages,
"Number of repeats is zero in: '" + OneEntry +
"' - if no repeats are needed the repeat should be omitted");
13335 SecondPassMessage(GiveMessages,
"Error in timetable - there appear to be no train services in the timetable, it must contain at least one");
13356 TwoLocationFlag =
false;
13362 SecondPassMessage(GiveMessages,
"Error in timetable - the following service has no listed events, there must be at least one: " + TDEntry.
HeadCode);
13376 SecondPassMessage(GiveMessages,
"Error in timetable - service must have a start event and at least one other for: " + TDEntry.
HeadCode);
13392 "Error in timetable - a signaller controlled service can have no more than one item (a repeat) after the start event, see: " +
13404 "Error in timetable - a signaller controlled service cannot have any other than a repeat after the start event, see: " + TDEntry.
HeadCode);
13430 SecondPassMessage(GiveMessages,
"Error in timetable - finish events Fns-sh and Frh-sh not permitted immediately after an Snt entry for: " +
13443 SecondPassMessage(GiveMessages,
"Error in timetable - only 'Frh' or 'Fjo' finish events are permitted immediately after an 'Sns' or 'Sfs' event for: " +
13450 if((AVEntry0.
Command ==
"Snt-sh") || (AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13456 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event can't immediately follow an 'Snt-sh', 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13466 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13471 SecondPassMessage(GiveMessages,
"Error in timetable - a start event is present that is not the first event for: " + TDEntry.
HeadCode);
13481 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13486 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat is present that is not the last item for: " + TDEntry.
HeadCode);
13496 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13507 SecondPassMessage(GiveMessages,
"Error in timetable - the last item must be either a finish event or a repeat for: " + TDEntry.
HeadCode);
13517 SecondPassMessage(GiveMessages,
"Error in timetable - the event immediately before the repeat must be a finish for: " + TDEntry.
HeadCode);
13529 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13536 SecondPassMessage(GiveMessages,
"Error in timetable - a finish event must be either the last or last but one for: " + TDEntry.
HeadCode);
13545 SecondPassMessage(GiveMessages,
"Error in timetable - the only event that can follow a finish event is a repeat for: " + TDEntry.
HeadCode);
13564 if((AVEntry0.
Command ==
"Snt") || (AVEntry0.
Command ==
"Snt-sh"))
13566 AnsiString LocationName =
"";
13580 SecondPassMessage(GiveMessages,
"Error in timetable - stopped 'Snt' or 'Snt-sh' followed by an illegal event for: " +
13581 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13590 if(AVEntry0.
Command ==
"Snt-sh")
13604 SecondPassMessage(GiveMessages,
"Error in timetable - unlocated 'Snt' not followed by 'Fer', 'pas' or an arrival for: " +
13620 SecondPassMessage(GiveMessages,
"Error in timetable - 'Sfs', 'Sns', 'Sns-sh', 'Snt-fsh' or 'Sns-fsh' followed by an illegal event for: " +
13621 TDEntry.
HeadCode +
". The event isn't valid for a stationary train.");
13633 bool FoundFlag =
false;
13637 if((AVEntry0.
Command ==
"Sns-sh") || (AVEntry0.
Command ==
"Sns-fsh"))
13639 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13651 SecondPassMessage(GiveMessages,
"Error in timetable - no location departure following an 'Sns-sh' or 'Sns-fsh' event for: " + TDEntry.
HeadCode);
13664 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13689 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13711 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13733 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13758 bool LocFoundFlag, FnsFoundFlag;
13762 LocFoundFlag =
false;
13763 FnsFoundFlag =
false;
13764 for(
int y =
TrainDataVector.at(x).ActionVector.size() - 1; y >= 0; y--)
13769 FnsFoundFlag =
true;
13778 LocFoundFlag =
true;
13789 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' finish must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13795 if(FnsFoundFlag && !LocFoundFlag)
13797 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' finish must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13810 if(AVEntry0.
Command ==
"Sns")
13822 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sns' event for: " + TDEntry.
HeadCode);
13830 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13831 ". The event isn't valid for a stationary train.");
13839 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sns' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13846 TDateTime SnsEventTime = AVEntry0.
EventTime;
13849 bool BreakFlag =
false;
13852 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13857 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SnsServiceRef)
13879 if(AVEntry0.
Command ==
"Sfs")
13881 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13889 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event must be followed by a departure and arrival before another split, see " +
TrainDataVector.at(x).ServiceReference);
13901 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13906 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
13926 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
13933 SecondPassMessage(GiveMessages,
"Error in timetable - an 'fsp' or 'rsp' event must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
13948 if(AVEntry0.
Command ==
"Sfs")
13960 SecondPassMessage(GiveMessages,
"Error in timetable - insufficient actions follwing an 'Sfs' event for: " + TDEntry.
HeadCode);
13968 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode +
13969 ". The event isn't valid for a stationary train.");
13977 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' event is followed by an illegal event for: " + TDEntry.
HeadCode);
13984 TDateTime SfsEventTime = AVEntry0.
EventTime;
13986 bool BreakFlag =
false;
13989 for(
unsigned int z = 0; z <
TrainDataVector.at(y).ActionVector.size(); z++)
13994 if(
TrainDataVector.at(y).ActionVector.at(z).OtherHeadCode == SfsServiceRef)
14014 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14019 for(
unsigned int z = y + 1; z <
TrainDataVector.at(x).ActionVector.size(); z++)
14040 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14047 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"' must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14052 else if((AVEntry.
Command ==
"Sns") || (AVEntry.
Command ==
"Sfs"))
14055 "Please make sure that the finish event of the service that links to this event is preceded by an "
14056 "event at the same location that has an identified location name, normally an arrival.");
14061 else if(AVEntry.
Command ==
"Snt-sh")
14064 "Please make sure that the service starts with zero speed and is at a named location.");
14069 else if((AVEntry.
Command ==
"Sns-fsh") || (AVEntry.
Command ==
"Sns-sh"))
14072 "Please make sure that the event is followed (not necessarily immediately) by a departure.");
14079 SecondPassMessage(GiveMessages,
"Error in timetable - '" + AVEntry.
Command +
"must be preceded by an event at the same location that has an identified location name, normally an arrival, see " +
TrainDataVector.at(x).ServiceReference);
14092 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14102 SecondPassMessage(GiveMessages,
"Error in timetable - only a repeat can follow a finish event for: " + TDEntry.
HeadCode);
14109 if(AVEntry.
Command ==
"F-nshs")
14114 SecondPassMessage(GiveMessages,
"Error in timetable - F-nshs (shuttle link) must be the last event for: " + TDEntry.
HeadCode);
14142 SecondPassMessage(GiveMessages,
"Error in timetable - a jbo event is followed by an illegal event for: " + TDEntry.
HeadCode +
14143 ". The event isn't valid for a stationary train.");
14153 SecondPassMessage(GiveMessages,
"Error in timetable - a train split can't be the last event for: " + TDEntry.
HeadCode);
14161 SecondPassMessage(GiveMessages,
"Error in timetable - a train split is followed by an illegal event for: " + TDEntry.
HeadCode +
14162 ". The event isn't valid for a stationary train.");
14180 SecondPassMessage(GiveMessages,
"Error in timetable - a 'cdt' is followed by an illegal event for: " + TDEntry.
HeadCode +
14181 ". The event isn't valid for a stationary train.");
14199 SecondPassMessage(GiveMessages,
"Error in timetable - a 'dsc' is followed by an illegal event for: " + TDEntry.
HeadCode +
14200 ". The event isn't valid for a stationary train.");
14210 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure can't be the last event for: " + TDEntry.
HeadCode);
14218 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure is followed by an illegal event for: " +
14219 TDEntry.
HeadCode +
". The event isn't valid for a moving train.");
14237 SecondPassMessage(GiveMessages,
"Error in timetable - a pass time is followed by an illegal event for: " + TDEntry.
HeadCode +
14238 ". The event isn't valid for a moving train.");
14260 bool LastEntryIsAnArrival =
false;
14267 LastEntryIsAnArrival =
false;
14268 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14275 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14277 if(LastEntryIsAnArrival)
14281 LastEntryIsAnArrival =
false;
14287 LastEntryIsAnArrival =
true;
14294 LastEntryIsAnArrival =
true;
14295 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14302 throw Exception(
"Timetable error, TimeLoc times not as initially set for " + TDEntry.
HeadCode);
14304 if(LastEntryIsAnArrival)
14308 LastEntryIsAnArrival =
false;
14314 LastEntryIsAnArrival =
true;
14324 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14332 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival can't be the last event for: " + TDEntry.
HeadCode);
14340 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival is followed by an illegal event for: " + TDEntry.
HeadCode +
14341 ". The event isn't valid for a stationary train.");
14352 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure can't be the last event for: " + TDEntry.
HeadCode);
14360 SecondPassMessage(GiveMessages,
"Error in timetable - a timed departure is followed by an illegal event for: " + TDEntry.
HeadCode +
14361 ". The event isn't valid for a moving train.");
14375 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14382 throw Exception(
"Timetable error, TimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14386 throw Exception(
"Timetable error, TimeLoc event has neither arrival nor departure time set for " + TDEntry.
HeadCode);
14393 throw Exception(
"Timetable error, TimeTimeLoc event has EventTime not -1 for " + TDEntry.
HeadCode);
14397 throw Exception(
"Timetable error, TimeTimeLoc event has either arrival or departure time not set for " + TDEntry.
HeadCode);
14406 throw Exception(
"Timetable error, Cmd or PassTime event has EventTime not set for " + TDEntry.
HeadCode);
14410 throw Exception(
"Timetable error, Cmd or PassTime event has either arrival or departure time set for " + TDEntry.
HeadCode);
14417 throw Exception(
"Timetable error, Repeat event has a time set for " + TDEntry.
HeadCode);
14428 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14443 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has a later arrival than departure time for: " +
14451 SecondPassMessage(GiveMessages,
"Error in timetable - a timed arrival and departure has too early an arrival time for: " +
14466 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14478 SecondPassMessage(GiveMessages,
"Error in timetable - a timed location event has a time that is too early for: " + TDEntry.
HeadCode);
14490 SecondPassMessage(GiveMessages,
"Error in timetable - a train event has a time that is set too early for: " + TDEntry.
HeadCode +
14491 ", may be before timetable start time");
14502 AnsiString LastLocationName =
"";
14506 bool LastEntryIsAnArrival =
false;
14511 LastEntryIsAnArrival =
false;
14512 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14513 if(LastLocationName !=
"")
14515 throw Exception(
"Timetable error, moving Snt event has LocationName set for " + TDEntry.
HeadCode);
14517 for(
unsigned int y = 1; y <
TrainDataVector.at(x).ActionVector.size();
14530 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14542 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14555 TwoLocationFlag =
true;
14560 LastEntryIsAnArrival =
false;
14564 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14567 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14572 else if(!LastEntryIsAnArrival && (AVEntry.
LocationName == LastLocationName))
14575 "Error in timetable - a location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode);
14581 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14587 LastEntryIsAnArrival =
true;
14588 LastLocationName =
TrainDataVector.at(x).ActionVector.at(0).LocationName;
14589 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14601 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14613 SecondPassMessage(GiveMessages,
"Error in timetable - a location event is inconsistent for: " + TDEntry.
HeadCode +
" && " +
14626 TwoLocationFlag =
true;
14631 LastEntryIsAnArrival =
false;
14635 if(LastEntryIsAnArrival && (AVEntry.
LocationName != LastLocationName))
14638 "Error in timetable - a location event for a timed departure is different from the arrival location for: " + TDEntry.
HeadCode);
14646 "A location event for a timed arrival is the same as the earlier departure location for: " + TDEntry.
HeadCode +
". Please correct if this is an error.\n\nThis warning will not be shown again.");
14653 LastEntryIsAnArrival = !LastEntryIsAnArrival;
14661 AnsiString LocationNameToBeChecked =
"";
14666 unsigned int y = 0;
14680 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
14681 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
14699 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
14708 TwoLocationFlag =
true;
14719 if(TwoLocationFlag)
14729 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14734 throw Exception(
"Error, non- 'Snt', 'Fer' or Repeat event doesn't have a location name set for " + TDEntry.
HeadCode);
14736 AnsiString LocName =
"";
14742 throw Exception(
"Error, 'Snt' event at a stop location doesn't have a location name set for " + TDEntry.
HeadCode);
14749 throw Exception(
"Error, 'Snt' unlocated event has a location name set for " + TDEntry.
HeadCode);
14772 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14797 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14819 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14841 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14860 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14863 if((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh"))
14878 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14883 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has FormatType unset for: " + TDEntry.
HeadCode);
14887 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has SequenceType unset for: " + TDEntry.
HeadCode);
14891 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has LocationType unset for: " + TDEntry.
HeadCode);
14895 throw Exception(
"Error - timetable ActionVector event no. " + AnsiString(y) +
" has ShuttleLinkType unset for: " + TDEntry.
HeadCode);
14934 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14936 AnsiString LocName =
TrainDataVector.at(x).ActionVector.at(y).LocationName;
14942 SecondPassMessage(GiveMessages,
"Error in timetable - continuation names (" + LocName +
") must not be included, see service " + HC);
14955 int IncMinutes = 0;
14965 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
14971 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat time exceeds 95h 59m, see service " + HC);
14977 if((
double)
TrainDataVector.at(x).ActionVector.at(y).ArrivalTime > -1)
14982 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
14988 if((
double)
TrainDataVector.at(x).ActionVector.at(y).DepartureTime > -1)
14993 SecondPassMessage(GiveMessages,
"Error in timetable - a repeat event time exceeds 95h 59m, see service " + HC);
15006 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15032 (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"F-nshs"));
15040 if(HeadCode.Length() > 4)
15042 HeadCode = HeadCode.SubString(HeadCode.Length() - 3, 4);
15053 int ForwardCount = 0;
15054 int ReverseCount = 0;
15056 if(MainHeadCode == SecondHeadCode)
15058 SecondPassMessage(GiveMessages,
"Error in timetable - Service " + MainHeadCode +
" has an event that references itself");
15067 if(TDEntry.
HeadCode == MainHeadCode)
15069 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15084 if(ForwardCount == 0)
15087 throw Exception(
"Error, ForwardCount == 0 in CheckForDuplicateCrossReferences after called with found values");
15089 if(ForwardCount > 2)
15092 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + SecondHeadCode +
" from a train whose headcode is " +
15093 MainHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15102 if(TDEntry.
HeadCode == SecondHeadCode)
15104 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15119 if(ReverseCount == 0)
15121 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + SecondHeadCode);
15126 if(ReverseCount > 2)
15129 SecondPassMessage(GiveMessages,
"Error in timetable - found more than two references to " + MainHeadCode +
" from a train whose headcode is " +
15130 SecondHeadCode +
". Check the service cross references from each service, and check whether one or other service is listed twice or more.");
15135 if(ForwardCount != ReverseCount)
15137 SecondPassMessage(GiveMessages,
"Error in timetable - " + MainHeadCode +
" has a different number of references to " + SecondHeadCode +
15138 " than the other way round");
15169 int ForwardCount = 0;
15170 int ReverseCount = 0;
15171 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
15180 if(TDEntry.
HeadCode == MainHeadCode)
15182 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15185 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15190 ForwardEntryPtr = &AVEntry;
15192 ForwardTDVectorNumber = x;
15195 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") ||
15196 (AVEntry.
Command ==
"Frh-sh")))
15201 ForwardEntryPtr = &AVEntry;
15203 ForwardTDVectorNumber = x;
15209 if(ForwardCount == 0)
15212 throw Exception(
"Error, ForwardCount == 0 in CheckCrossReferencesAndSetData after called with found values");
15214 if(ForwardCount > 1)
15216 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + OtherHeadCode +
" from a train whose headcode is " +
15226 if(TDEntry.
HeadCode == OtherHeadCode)
15228 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
15231 if(!Shuttle && (AVEntry.
Command !=
"Sns-sh") && (AVEntry.
Command !=
"Snt-sh") && (AVEntry.
Command !=
"Fns-sh") && (AVEntry.
Command !=
"Frh-sh"))
15237 ReverseEntryPtr = &AVEntry;
15238 ReverseTDVectorNumber = x;
15241 else if(Shuttle && ((AVEntry.
Command ==
"Sns-sh") || (AVEntry.
Command ==
"Snt-sh") || (AVEntry.
Command ==
"Fns-sh") || (AVEntry.
Command ==
"Frh-sh")))
15247 ReverseEntryPtr = &AVEntry;
15248 ReverseTDVectorNumber = x;
15255 if(ReverseCount == 0)
15257 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + OtherHeadCode);
15262 if(ReverseCount > 1)
15264 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
15271 bool ForwardShuttleStart = ((ForwardEntryPtr->Command ==
"Sns-sh") || (ForwardEntryPtr->Command ==
"Snt-sh"));
15272 bool ForwardShuttleFinish = ((ForwardEntryPtr->Command ==
"Fns-sh") || (ForwardEntryPtr->Command ==
"Frh-sh"));
15273 bool ReverseShuttleStart = ((ReverseEntryPtr->
Command ==
"Sns-sh") || (ReverseEntryPtr->
Command ==
"Snt-sh"));
15274 bool ReverseShuttleFinish = ((ReverseEntryPtr->
Command ==
"Fns-sh") || (ReverseEntryPtr->
Command ==
"Frh-sh"));
15278 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat");
15285 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + OtherHeadCode +
" does not have a repeat");
15290 if(SetDataAndCheckLocations)
15292 if(ForwardEntryPtr->LocationName ==
"")
15294 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15295 ". One or other service does not have a location set");
15302 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + OtherHeadCode +
15303 ". One or other service does not have a location set");
15308 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
15310 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15311 " is at a different location to the referencing train " + MainHeadCode);
15320 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
15322 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + OtherHeadCode +
15323 " has a different event time to the referencing train " + MainHeadCode);
15331 if(ForwardShuttleStart && ReverseShuttleFinish)
15336 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle service " + MainHeadCode +
15337 " first repeat restart time not consistent with finish service " + OtherHeadCode);
15343 if((ReverseEntryPtr->
Command ==
"Sfs") || (ReverseEntryPtr->
Command ==
"Sns"))
15346 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15348 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Sfs' or 'Sns' event (" + OtherHeadCode +
15349 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15355 if(ReverseEntryPtr->
Command ==
"Fjo")
15358 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15360 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fjo' event (" + OtherHeadCode +
15361 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15367 if(ReverseEntryPtr->
Command ==
"Fns")
15370 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
15372 SecondPassMessage(GiveMessages,
"Error in timetable - an 'Fns' event (" + OtherHeadCode +
15373 ") appears in the same sequence as the corresponding linked event " + MainHeadCode);
15379 if(ForwardEntryPtr->Command ==
"Sfs")
15381 if((ReverseEntryPtr->
Command !=
"fsp") && (ReverseEntryPtr->
Command !=
"rsp"))
15384 "Error in timetable - unable to find a corresponding split train event for the train that starts from a split whose headcode is " +
15391 if((ForwardEntryPtr->Command ==
"fsp") || (ForwardEntryPtr->Command ==
"rsp"))
15393 if(ReverseEntryPtr->
Command !=
"Sfs")
15395 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sfs' event for the train split whose headcode is " +
15403 if(SetDataAndCheckLocations)
15407 SecondPassMessage(GiveMessages,
"Error in timetable - can't find timetabled location '" + ForwardEntryPtr->LocationName +
"' in railway - perhaps there are concourses without platforms?");
15414 SecondPassMessage(GiveMessages,
"Error in timetable - can't find any named location elements at '" + ForwardEntryPtr->LocationName +
"' - perhaps there are concourses without platforms?");
15421 SecondPassMessage(GiveMessages,
"Error in timetable - location too short to split a train at " + ForwardEntryPtr->LocationName);
15426 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15438 if(ForwardEntryPtr->Command ==
"Sns")
15440 if(ReverseEntryPtr->
Command !=
"Fns")
15442 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fns' event for the 'Sns' train whose headcode is " +
15443 MainHeadCode +
" and is formed from a service with headcode " + OtherHeadCode);
15449 if(ForwardEntryPtr->Command ==
"Fns")
15451 if(ReverseEntryPtr->
Command !=
"Sns")
15453 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns' event for the train whose headcode is " + MainHeadCode +
15454 " and forms a new service with headcode " + OtherHeadCode);
15461 if(SetDataAndCheckLocations)
15463 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15475 if(ForwardEntryPtr->Command ==
"jbo")
15477 if(ReverseEntryPtr->
Command !=
"Fjo")
15479 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Fjo' event for the train whose headcode is " + MainHeadCode +
15480 " and is joined by a train with headcode " + OtherHeadCode);
15486 if(ForwardEntryPtr->Command ==
"Fjo")
15488 if(ReverseEntryPtr->
Command !=
"jbo")
15490 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'jbo' event for the train whose headcode is " + MainHeadCode +
15491 " and joins a train with headcode " + OtherHeadCode);
15498 if(SetDataAndCheckLocations)
15500 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15516 if(ForwardShuttleStart)
15519 if(!ReverseShuttleFinish)
15522 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + MainHeadCode +
15523 " from train whose headcode is " + OtherHeadCode +
", has to be Fns-sh, Frh-sh");
15529 if(ReverseShuttleStart)
15532 if(!ForwardShuttleFinish)
15535 SecondPassMessage(GiveMessages,
"Error in timetable - incorrect shuttle link to train whose headcode is " + OtherHeadCode +
15536 " from train whose headcode is " + MainHeadCode +
", has to be Fns-sh, Frh-sh");
15543 if(SetDataAndCheckLocations)
15545 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
15558 bool MainRepeat =
false, OtherRepeat =
false;
15568 OtherRepeat =
true;
15571 if((MainRepeat && !OtherRepeat) || (!MainRepeat && OtherRepeat))
15573 SecondPassMessage(GiveMessages,
"Error in timetable - only one repeat is provided for the train whose headcode is " + MainHeadCode +
15574 " and the associated train with headcode " + OtherHeadCode);
15579 if(MainRepeat && OtherRepeat)
15585 SecondPassMessage(GiveMessages,
"Error in timetable - repeat items don't correspond for the train whose headcode is " + MainHeadCode +
15586 " and the associated train with headcode " + OtherHeadCode);
15608 while(Input[1] ==
' ')
15610 if(Input.Length() > 1)
15612 Input = Input.SubString(2, Input.Length() - 1);
15626 while(Input[Input.Length()] ==
' ')
15628 if(Input.Length() > 1)
15630 Input = Input.SubString(1, Input.Length() - 1);
15640 AnsiString Output =
"";
15641 bool DelimiterFound =
false;
15643 for(
int x = 1; x < Input.Length() + 1; x++)
15647 if(Input[x] ==
' ')
15652 if((Input[x] !=
',') && (Input[x] !=
';'))
15654 DelimiterFound =
false;
15655 Output = Output + Input[x];
15659 DelimiterFound =
true;
15660 Output = Output + Input[x];
15672 DelimiterFound =
false;
15673 for(
int x = Input.Length(); x > 0; x--)
15677 if(Input[x] ==
' ')
15682 if((Input[x] !=
',') && (Input[x] !=
';'))
15684 DelimiterFound =
false;
15685 Output = AnsiString(Input[x]) + Output;
15689 DelimiterFound =
true;
15690 Output = AnsiString(Input[x]) + Output;
15715 if((AVEntry0.
Command !=
"Snt") && (AVEntry0.
Command !=
"Snt-sh"))
15717 throw Exception(
"Error, first event not 'Snt' or 'Snt-sh' in IsSNTEntryLocated");
15729 LocationName = LocRear;
15733 LocationName = LocFront;
15735 if(LocationName ==
"")
15756 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
15797 int RearPosition = 0, FrontPosition = 0, RearExitPos = 0;
15800 if(RearPosition < 0)
15807 if(FrontPosition < 0)
15818 for(
int x = 0; x < 4; x++)
15820 if(RearTrackElement.
Conn[x] == FrontPosition)
15835 TimetableMessage(GiveMessages,
"Front of train attempting to start on a continuation at: " + FrontElementStr);
15842 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + FrontElementStr);
15848 TimetableMessage(GiveMessages,
"Train attempting to start on a level crossing at: " + RearElementStr);
15853 if((RearType ==
Points) && (RearExitPos == 3))
15855 TimetableMessage(GiveMessages,
"Front of train attempting to start on element connected to diverging points at: " + RearElementStr);
15861 TimetableMessage(GiveMessages,
"Rear of train attempting to start on element connected to diverging points at: " + FrontElementStr);
15876 AnsiString(RearExitPos));
15887 int FrontPosition = RearTrackElement.
Conn[RearExitPos];
15889 int FrontEntryPos = RearTrackElement.
ConnLinkPos[RearExitPos];
15892 AnsiString RearName, FrontName;
15908 FrontName = FrontTrackElement.
ElementID;
15911 int LockedVectorNumber;
16081 "," + AnsiString(IncDigits));
16084 throw Exception(
"Error, last 2 characters not both digits and IncDigits > 0 in GetRepeatHeadCode");
16089 return(BaseHeadCode);
16091 int BaseDigits = BaseHeadCode.SubString(3, 2).ToInt();
16092 int NextRepeatDigits = BaseDigits + (IncDigits * RepeatNumber);
16094 while(NextRepeatDigits >= 100)
16096 NextRepeatDigits -= 100;
16098 AnsiString NextRepeatDigitsStr = AnsiString(NextRepeatDigits);
16100 if(NextRepeatDigitsStr.Length() < 2)
16102 NextRepeatDigitsStr = AnsiString(
'0') + NextRepeatDigitsStr;
16104 AnsiString NextRepeatHeadCode = BaseHeadCode.SubString(1, 2) + NextRepeatDigitsStr;
16107 return(NextRepeatHeadCode);
16115 AnsiString(RepeatNumber) +
"," + AnsiString(IncMinutes));
16116 TDateTime NextRepeatTime = BasicTime + TDateTime(((
double)(RepeatNumber * IncMinutes)) / 1440.0);
16118 return(NextRepeatTime);
16127 AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes));
16128 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16129 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16130 int RepeatSecs = RepeatMinutes * 60;
16132 if((ForwardSecs > (ReverseSecs - RepeatSecs + 10)) || (ForwardSecs < (ReverseSecs - RepeatSecs - 10)))
16166 NonRepeatingHeadCode);
16167 int ForwardCount = 0;
16168 int ReverseCount = 0;
16169 unsigned int ForwardTDVectorNumber, ReverseTDVectorNumber;
16179 if(TDEntry.
HeadCode == MainHeadCode)
16181 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16187 ForwardEntryPtr = &AVEntry;
16189 ForwardTDVectorNumber = x;
16194 if(ForwardCount == 0)
16197 throw Exception(
"Error, ForwardCount == 0 in CheckNonRepeatingShuttleLinksAndSetData after called with found values");
16199 if(ForwardCount > 1)
16201 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + NonRepeatingHeadCode +
" from a train whose headcode is " +
16211 if(TDEntry.
HeadCode == NonRepeatingHeadCode)
16213 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16220 ReverseEntryPtr = &AVEntry;
16221 ReverseTDVectorNumber = x;
16227 if(ReverseCount == 0)
16229 SecondPassMessage(GiveMessages,
"Error in timetable - cross reference missing in either " + MainHeadCode +
" or " + NonRepeatingHeadCode);
16234 if(ReverseCount > 1)
16236 SecondPassMessage(GiveMessages,
"Error in timetable - found more than one reference to " + MainHeadCode +
" from a train whose headcode is " +
16237 NonRepeatingHeadCode);
16242 if(((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh")) && (MainTrainDataPtr->
ActionVector.back().FormatType ==
Repeat))
16244 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle connecting train " + MainHeadCode +
" shouldn't have a repeat");
16249 if((ForwardEntryPtr->Command !=
"F-nshs") && (ForwardEntryPtr->Command !=
"Sns-fsh") && (MainTrainDataPtr->
ActionVector.back().FormatType !=
Repeat))
16251 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle train " + MainHeadCode +
" does not have a repeat item");
16256 if(SetDataAndCheckLocations)
16258 if(ForwardEntryPtr->LocationName ==
"")
16260 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16261 ". One or other service does not have a location set");
16268 SecondPassMessage(GiveMessages,
"Error in timetable - location error in cross referenced trains " + MainHeadCode +
" and " + NonRepeatingHeadCode +
16269 ". One or other service does not have a location set");
16274 if(ForwardEntryPtr->LocationName != ReverseEntryPtr->
LocationName)
16276 SecondPassMessage(GiveMessages,
"Error in timetable - cross referenced train " + NonRepeatingHeadCode +
16277 " is at a different location to the referencing train " + MainHeadCode);
16283 if(ForwardEntryPtr->Command ==
"F-nshs")
16286 if(ForwardEntryPtr->EventTime != ReverseEntryPtr->
EventTime)
16288 SecondPassMessage(GiveMessages,
"Error in timetable - shuttle in-link service " + MainHeadCode +
16289 " finish time not consistent with start time of shuttle service " + NonRepeatingHeadCode);
16295 if(ForwardEntryPtr->Command ==
"Fns-sh")
16299 MainTrainDataPtr->
ActionVector.back().RearStartOrRepeatMins, MainTrainDataPtr->
ActionVector.back().NumberOfRepeats))
16301 SecondPassMessage(GiveMessages,
"Error in timetable - service " + NonRepeatingHeadCode +
", which links out from shuttle service " + MainHeadCode +
16302 ", has the wrong start time. It should correspond to the finish time of the last shuttle.");
16308 if((ForwardEntryPtr->Command ==
"F-nshs") || (ForwardEntryPtr->Command ==
"Sns-fsh"))
16311 if(ReverseTDVectorNumber == ForwardTDVectorNumber)
16313 SecondPassMessage(GiveMessages,
"Error in timetable - the non repeating link service " + NonRepeatingHeadCode +
16314 " appears in the same sequence as the corresponding shuttle service " + MainHeadCode);
16332 if(ForwardEntryPtr->Command ==
"Sns-sh")
16334 if(ReverseEntryPtr->
Command !=
"F-nshs")
16336 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'F-nshs' event for the 'Sns-sh' train whose headcode is " +
16337 MainHeadCode +
" and is a new shuttle service formed from the service with headcode " + NonRepeatingHeadCode);
16343 if(ForwardEntryPtr->Command ==
"F-nshs")
16345 if(ReverseEntryPtr->
Command !=
"Sns-sh")
16347 SecondPassMessage(GiveMessages,
"Error in timetable - unable to find a corresponding 'Sns-sh' event for the 'F-nshs' train whose headcode is " +
16348 MainHeadCode +
" and forms a new shuttle service with headcode " + NonRepeatingHeadCode);
16355 if(SetDataAndCheckLocations)
16357 ForwardEntryPtr->LinkedTrainEntryPtr = OtherTrainDataPtr;
16369 if(ForwardEntryPtr->Command ==
"Sns-fsh")
16371 if(ReverseEntryPtr->
Command !=
"Fns-sh")
16374 "Error in timetable - unable to find a corresponding 'Fns-sh' event for the 'Sns-fsh' non-shuttle service whose headcode is " + MainHeadCode +
16375 " formed from a shuttle service with headcode " + NonRepeatingHeadCode);
16381 if(ForwardEntryPtr->Command ==
"Fns-sh")
16383 if(ReverseEntryPtr->
Command !=
"Sns-fsh")
16386 "Error in timetable - unable to find a corresponding 'Sns-fsh' event for the 'Fns-sh' shuttle service whose headcode is " + MainHeadCode +
16387 " and forms a new non-shuttle service with headcode " + NonRepeatingHeadCode);
16394 if(SetDataAndCheckLocations)
16396 ForwardEntryPtr->NonRepeatingShuttleLinkEntryPtr = OtherTrainDataPtr;
16420 +
"," + AnsiString(
double(ReverseEventTime)) +
"," + AnsiString(RepeatMinutes) +
"," + AnsiString(RepeatNumber));
16421 int ForwardSecs = int(
double(ForwardEventTime) * 86400);
16422 int ReverseSecs = int(
double(ReverseEventTime) * 86400);
16423 int RepeatSecs = RepeatMinutes * RepeatNumber * 60;
16425 if((ReverseSecs > (ForwardSecs + RepeatSecs + 10)) || (ReverseSecs < (ForwardSecs + RepeatSecs - 10)))
16449 throw Exception(
"Error - last entry in " + TDEntryPtr->
HeadCode +
" service is not a repeat - should have already found this error");
16452 AnsiString OriginalHeadCode = TDEntryPtr->
HeadCode;
16453 AnsiString LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16455 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16457 SecondPassMessage(GiveMessages,
"Error in timetable - last event in shuttle service " + TDEntryPtr->
HeadCode +
" is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16462 while(LastActionCommand ==
"Fns")
16464 TDEntryPtr = (TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr;
16465 LastActionCommand = (TDEntryPtr->
ActionVector.end() - 2)->Command;
16466 if((LastActionCommand !=
"Fns") && (LastActionCommand !=
"Fns-sh") && (LastActionCommand !=
"Frh-sh"))
16469 "Error in timetable - last event in a continuation shuttle service (i.e links back to a shuttle) whose headcode is " + TDEntryPtr->
HeadCode +
16470 " is not 'Fns', 'Fns-sh' or 'Frh-sh'");
16477 if((TDEntryPtr->
ActionVector.end() - 2)->LinkedTrainEntryPtr != ShuttleStartAddress)
16480 " is a shuttle finish, but it doesn't link back to the start of the original shuttle starting service " + OriginalHeadCode +
16481 ". The linking of two or more shuttles is not permitted.");
16519 ShowMessage(Message);
16528 int Mins = Input, Hrs = 0;
16534 AnsiString AnsiMins = AnsiString(Mins);
16535 if(AnsiMins.Length() == 1)
16537 AnsiMins =
"0" + AnsiMins;
16539 AnsiString AnsiHrs = AnsiString(Hrs);
16540 if(AnsiHrs.Length() == 1)
16542 AnsiHrs =
"0" + AnsiHrs;
16545 return(AnsiHrs +
':' + AnsiMins);
16585 AnsiString(ActionEventType) +
"," + LocationID);
16586 AnsiString BaseLog =
"", Prefix =
"", ErrorLog =
"", WarningStr =
"";
16591 Prefix =
" ERROR: ";
16594 Prefix =
" HELD: ";
16595 ErrorLog =
" can't enter railway, train obstructing entry position ";
16596 WarningStr =
" can't enter railway, train obstructing entry position ";
16601 Prefix =
" HELD: ";
16602 ErrorLog =
" can't enter railway, route set against it at entry position ";
16603 WarningStr =
" can't enter railway, route set against it at entry position ";
16608 Prefix =
" HELD: ";
16609 ErrorLog =
" can't be created, train obstructing ";
16610 WarningStr =
" can't be created, train obstructing ";
16615 Prefix =
" HELD: ";
16616 ErrorLog =
" can't be created on a locked route at ";
16617 WarningStr =
" can't be created on a locked route at ";
16622 Prefix =
" HELD: ";
16623 ErrorLog =
" can't enter on a locked route at ";
16624 WarningStr =
" can't enter on a locked route at ";
16629 Prefix =
" HELD: ";
16630 ErrorLog =
" can't be created, diverging points at ";
16631 WarningStr =
" can't be created, diverging points at ";
16636 ErrorLog =
" left railway unexpectedly at ";
16641 ErrorLog =
" left railway at an incorrect exit at ";
16646 ErrorLog =
" failed to split - location too short at ";
16647 WarningStr =
" failed to split, location too short at ";
16652 Prefix =
" HELD: ";
16653 ErrorLog =
" unable to split - other train obstructing at ";
16654 WarningStr =
" unable to split - other train obstructing at ";
16659 ErrorLog =
" stopped at buffers unexpectedly at position ";
16663 ErrorLog =
" failed to stop at ";
16668 ErrorLog =
" failed to split at ";
16673 ErrorLog =
" failed to be joined by other train at ";
16678 ErrorLog =
" failed to change its description at ";
16683 ErrorLog =
" failed to join other train at ";
16688 ErrorLog =
" failed to terminate at ";
16693 ErrorLog =
" failed to form new service at ";
16698 ErrorLog =
" failed to exit railway ";
16703 ErrorLog =
" failed to change direction at ";
16708 ErrorLog =
" failed to pass ";
16713 ErrorLog =
" facing buffers and unable to start at ";
16717 ErrorLog =
" DERAILED at position ";
16718 Prefix =
" DERAILMENT: ";
16723 ErrorLog =
" CRASHED INTO BUFFERS at ";
16724 Prefix =
" CRASH: ";
16729 ErrorLog =
" CRASHED INTO ROAD TRAFFIC AT A LEVEL CROSSING at ";
16730 Prefix =
" CRASH: ";
16735 ErrorLog =
" CRASHED INTO " + OtherHeadCode +
" at position ";
16736 Prefix =
" CRASH: ";
16740 else if(ActionEventType ==
FailSPAD)
16742 ErrorLog =
" PASSED SIGNAL AT DANGER at position ";
16743 Prefix =
" SPAD: ";
16748 ErrorLog =
"Signals reset ahead of train, route cancelled at position ";
16749 Prefix =
" SPAD RISK: ";
16754 ErrorLog =
" forced a route cancellation by occupying it incorrectly at ";
16758 Prefix =
" WARNING: ";
16759 ErrorLog =
" waiting to join " + OtherHeadCode +
" at ";
16760 WarningStr =
" waiting to join " + OtherHeadCode +
" at ";
16765 Prefix =
" WARNING: ";
16766 ErrorLog =
" waiting to be joined by " + OtherHeadCode +
" at ";
16767 WarningStr =
" waiting to be joined by " + OtherHeadCode +
" at ";
16805 std::ofstream OutFile(
"TrainData.csv");
16809 ShowMessage(
"Output file TrainData.csv failed to open");
16816 OutFile <<
"HeadCode" <<
',' <<
"Description" <<
',' <<
"StartSpeed" <<
',' <<
"MaxRunningSpeed" <<
',' <<
"NumberOfTrains" <<
'\n' <<
'\n';
16821 OutFile <<
',' <<
"FormatType" <<
',' <<
"EventTime" <<
',' <<
"ArrivalTime" <<
',' <<
"DepartureTime" <<
',' <<
"LocationName" <<
',' <<
"Command" <<
16822 ',' <<
"OtherHeadCode" <<
',' <<
"LinkedTrainEntryPtr" <<
',' <<
"RearStartOrRepeatMins" <<
',' <<
"FrontStartOrRepeatDigits" <<
',' <<
16823 "RepeatNumber" <<
'\n' <<
'\n';
16824 for(
unsigned int y = 0; y <
TrainDataVector.at(x).ActionVector.size(); y++)
16827 AnsiString TimetableEntryTypeStr;
16833 TimetableEntryTypeStr =
"NoFormat";
16839 TimetableEntryTypeStr =
"TimeLoc";
16845 TimetableEntryTypeStr =
"TimeTimeLoc";
16851 TimetableEntryTypeStr =
"TimeCmd";
16857 TimetableEntryTypeStr =
"StartNew";
16863 TimetableEntryTypeStr =
"TimeCmdHeadCode";
16869 TimetableEntryTypeStr =
"FinRemHere";
16875 TimetableEntryTypeStr =
"FNSShuttle";
16881 TimetableEntryTypeStr =
"SNTShuttle";
16887 TimetableEntryTypeStr =
"SNSShuttle";
16893 TimetableEntryTypeStr =
"SNSNonRepeatFromShuttle";
16899 TimetableEntryTypeStr =
"FSHNewService";
16905 TimetableEntryTypeStr =
"Repeat";
16911 TimetableEntryTypeStr =
"Default";
16922 OutFile <<
',' <<
',' <<
"Mass" <<
',' <<
"MaxBrakeRate" <<
',' <<
"PowerAtRail" <<
',' <<
"TrainID" <<
',' <<
"RunningEntry" <<
'\n' <<
'\n';
16923 for(
unsigned int y = 0; y <
TrainDataVector.at(x).TrainOperatingDataVector.size(); y++)
16926 AnsiString RunningEntryStr;
16932 RunningEntryStr =
"NotStarted";
16938 RunningEntryStr =
"Running";
16944 RunningEntryStr =
"Exited";
16948 OutFile <<
',' <<
',' << TOD.
TrainID <<
',' << RunningEntryStr.c_str() <<
',' <<
'\n';
16965 ShowMessage(Message);
16966 BaseTime = TDateTime::CurrentDateTime();
16980 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
16993 TTrain *NewTrain =
new TTrain(1, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
16995 for(
int x = 0; x < NumberOfTrains; x++)
16997 *NewTrain =
TTrain(2, 0, 0,
"", 0, 1, 0, 0, 0, (
TTrainMode)0, 0, 0, 0, 0, 0);
17017 int NumberOfTrains;
17024 for(
int x = 0; x < NumberOfTrains; x++)
17061 for(
int x = 0; x < LockedRouteVectorSize; x++)
17068 LockedRouteObject.
LockStartTime = TDateTime(LockStartTimeDouble);
17079 int LockedRouteVectorSize;
17086 for(
int x = 0; x < LockedRouteVectorSize; x++)
17144 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17152 ContinuationAutoSigObject.
PassoutTime = TDateTime(PassoutTimeDouble);
17163 int ContinuationAutoSigVectorSize;
17170 for(
int x = 0; x < ContinuationAutoSigVectorSize; x++)
17240 if(AVFirstEntry.
Command ==
"Snt")
17264 CTEMMP.second = CTEEntry;
17271 throw Exception(
"Error, Last ActionVectorEntry not a repeat in BuildContinuationTrainExpectationMultiMap");
17279 CTEMMP.second = CTEEntry;
17300 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
17317 if((VecPos < 0) || (VecPos >= (
int)
TrainVector.size()))
17319 throw Exception(
"Out of Range Error, vector size: " + AnsiString(
TrainVector.size()) +
", VecPos: " + AnsiString(VecPos) +
" in TrainVectorAt");
17330 AnsiString RetStr =
"", PartStr =
"";
17445 AnsiString TTFileName = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17449 TTFileName = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
17451 AnsiString ShortTTName =
"";
17453 for(
int x = TTFileName.Length(); x > 0; x--)
17455 if(TTFileName[x] ==
'\\')
17457 ShortTTName = TTFileName.SubString(x + 1, TTFileName.Length() - x - 4);
17462 ShowMessage(
"Creates two timetables named " + ShortTTName +
17463 " in the 'Formatted timetables' folder, one in service order in '.csv' format, and one in chronological order in '.txt' format");
17465 Screen->Cursor = TCursor(-11);
17467 AnsiString FormatNoDPStr =
"#######0";
17468 AnsiString TableTitle =
"", TimetableTimeStr =
"", MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"", FirstHeadCode =
"", Header =
"";
17471 TableTitle =
"Railway: " + RailwayTitle +
"; Timetable: " + TimetableTitle +
"; Start time: " + TimetableTimeStr;
17478 MassStr =
"", PowerStr =
"", BrakeStr =
"", MaxSpeedStr =
"";
17480 if(TrainDataEntry.
Mass > 0)
17482 MassStr =
"; Mass " + AnsiString::FormatFloat(FormatNoDPStr, ((
double)TrainDataEntry.
Mass) / 1000) +
"Te; ";
17486 PowerStr =
"Power " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
PowerAtRail / 1000 / 0.8) +
"kW; ";
17490 BrakeStr =
"Brake force " + AnsiString::FormatFloat(FormatNoDPStr, (TrainDataEntry.
MaxBrakeRate * TrainDataEntry.
Mass / 9810)) +
"Te; ";
17494 MaxSpeedStr =
"Maximum speed " + AnsiString::FormatFloat(FormatNoDPStr, TrainDataEntry.
MaxRunningSpeed) +
" km/h";
17496 FirstHeadCode = TrainDataEntry.
HeadCode;
17497 int IncDigits = 0, IncMinutes = 0;
17499 if(!ActionVector.empty())
17501 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
17503 IncDigits = ActionVector.at(ActionVector.size() - 1).FrontStartOrRepeatDigits;
17504 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
17522 for(
unsigned int z = 0; z < ActionVector.size(); z++)
17527 AnsiString PartStr =
"", TimeStr =
"";
17544 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17548 PartStr =
"Created at " + ActionVectorEntry.
LocationName;
17558 PartStr =
"Enters at " + LocName;
17571 PartStr =
"Created at " + LocName;
17585 PartStr =
"Enters at " + ActionVectorEntry.
LocationName;
17590 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17596 else if(ActionVectorEntry.
Command ==
"Sfs")
17598 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" split from";
17602 else if(ActionVectorEntry.
Command ==
"Sns")
17604 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17612 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17618 PartStr =
"Repeat shuttle service at " + ActionVectorEntry.
LocationName +
" from ";
17626 PartStr =
"New service at " + ActionVectorEntry.
LocationName +
" from";
17629 AnsiString FirstHeadCode = TDE->
HeadCode;
17633 TimeStr =
GetRepeatHeadCode(36, FirstHeadCode, LastRepeatNumber, IncrementalDigits) +
" at " +
17645 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17647 OneTTEntry.
Action = PartStr;
17648 OneTTEntry.
Time = TimeStr;
17650 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17655 PartStr =
"Arrives & departs " + ActionVectorEntry.
LocationName;
17661 PartStr =
"Arrives at " + ActionVectorEntry.
LocationName;
17666 PartStr =
"Departs from " + ActionVectorEntry.
LocationName;
17674 else if(ActionVectorEntry.
Command ==
"jbo")
17676 PartStr =
"Joined at " + ActionVectorEntry.
LocationName +
" by";
17680 else if(ActionVectorEntry.
Command ==
"fsp")
17684 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17688 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17693 else if(ActionVectorEntry.
Command ==
"rsp")
17697 PartStr =
"Splits from front [mass%-power% = " + ActionVectorEntry.
SplitDistribution +
"] at " + ActionVectorEntry.
LocationName +
" to form";
17701 PartStr =
"Splits from front [mass%-power% = 50-50] at " + ActionVectorEntry.
LocationName +
" to form";
17706 else if(ActionVectorEntry.
Command ==
"cdt")
17708 PartStr =
"Changes direction at " + ActionVectorEntry.
LocationName;
17711 else if(ActionVectorEntry.
Command ==
"dsc")
17713 PartStr =
"Changes description at " + ActionVectorEntry.
LocationName;
17719 if(ActionVectorEntry.
Command ==
"Fns")
17721 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17725 else if(ActionVectorEntry.
Command ==
"F-nshs")
17727 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17733 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service ";
17740 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17746 PartStr =
"At " + ActionVectorEntry.
LocationName +
" forms new service";
17753 PartStr =
"Terminates shuttle service at " + ActionVectorEntry.
LocationName;
17758 else if(ActionVectorEntry.
Command ==
"Frh")
17760 PartStr =
"Terminates at " + ActionVectorEntry.
LocationName;
17765 if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
17769 else if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
17779 else if(ActionVectorEntry.
Command ==
"Fer")
17781 AnsiString AllowedExits;
17785 else if(ActionVectorEntry.
Command ==
"Fjo")
17787 PartStr =
"At " + ActionVectorEntry.
LocationName +
" joins";
17796 OneTTEntry.
Action = PartStr;
17797 OneTTEntry.
Time = TimeStr;
17804 AllTTTrains->push_back(OneTTLine);
17808 std::ofstream TTFile(TTFileName.c_str());
17812 StopTTClockMessage(64,
"Formatted timetable file failed to open - can't be created");
17813 delete AllTTTrains;
17848 TTFile << TableTitle.c_str() <<
'\n' <<
'\n';
17849 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17851 TTFile << AllTTTrains->at(x).Header.c_str();
17854 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17856 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17858 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str() <<
',';
17862 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode.c_str();
17865 TTFile <<
'\n' <<
'\n';
17867 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.size(); z++)
17869 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(0).OneFormattedTrainVector.at(z).Action.c_str() <<
',';
17870 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17872 if(y < (AllTTTrains->at(x).NumberOfTrains - 1))
17874 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str() <<
',';
17878 TTFile << AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time.c_str();
17883 TTFile <<
'\n' <<
'\n';
17888 AnsiString TTFileName2 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
17890 TTFileName2 = CurDir +
"\\Formatted timetables\\Timetable " + TTFileName2 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".txt";
17892 std::ofstream TTFile2(TTFileName2.c_str());
17896 StopTTClockMessage(67,
"Chronological timetable file failed to open - can't be created");
17897 delete AllTTTrains;
17901 typedef std::multimap<AnsiString, AnsiString>TAnsiMultiMap;
17902 std::multimap<AnsiString, AnsiString>::iterator AMMIT;
17903 std::pair<AnsiString, AnsiString>AnsiMultiMapEntry;
17905 TAnsiMultiMap *TAMM =
new TAnsiMultiMap;
17910 TTFile2 << TableTitle.c_str() <<
'\n' <<
'\n';
17911 for(
unsigned int x = 0; x < AllTTTrains->size(); x++)
17913 for(
int y = 0; y < AllTTTrains->at(x).NumberOfTrains; y++)
17915 for(
unsigned int z = 0; z < AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.size(); z++)
17917 bool GiveMessagesFalse =
false;
17918 AnsiString TimeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Time;
17919 AnsiString HeadCodeString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).HeadCode;
17920 AnsiString ActionString = AllTTTrains->at(x).OneCompleteFormattedTrainVector.at(y).OneFormattedTrainVector.at(z).Action;
17925 AnsiString OtherHeadCode = TimeString.SubString(1, 4);
17926 TimeString = TimeString.SubString(9, 5);
17927 ActionString +=
" " + OtherHeadCode;
17929 if(TimeString.SubString(1, 7) ==
"End at ")
17932 TimeString = TimeString.SubString(8, 5);
17934 AnsiString OneLine = TimeString +
' ' + HeadCodeString +
' ' + ActionString +
'\n';
17935 AnsiMultiMapEntry.first = TimeString;
17936 AnsiMultiMapEntry.second = OneLine;
17937 TAMM->insert(AnsiMultiMapEntry);
17942 for(AMMIT = TAMM->begin(); AMMIT != TAMM->end(); AMMIT++)
17944 TTFile2 << (AMMIT->second).c_str();
17946 delete AllTTTrains;
17955 bool AtLocChecked,
bool DirChecked,
int ArrRange,
int DepRange)
17959 bool AnalysisError =
false;
17960 AnsiString SequenceLog =
"SequenceLog\n";
18003 TTrainDataVector::iterator TDVIt, TDVCopyIt;
18005 int IteratorNumber = 0;
18006 AnsiString AnsiSuffix =
"";
18013 if(TDVCopyIt->HeadCode == TDVIt->HeadCode)
18016 AnsiSuffix = AnsiString(Suffix);
18017 TDVCopyIt->ServiceReference = TDVIt->HeadCode +
"/" + AnsiSuffix;
18018 TDVCopyIt->HeadCode = TDVIt->HeadCode +
"/" + AnsiSuffix;
18024 int Increment = 0, SlashPos;
18026 AnsiString LinkedHeadCode;
18030 for(AVEIt = TDVCopyIt->ActionVector.begin(); AVEIt != TDVCopyIt->ActionVector.end(); AVEIt++)
18032 if(AVEIt->LinkedTrainEntryPtr != NULL)
18041 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18043 if(LinkedHeadCode[x] ==
'/')
18045 SlashPos = LinkedHeadCode.Length() - x + 1;
18048 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18049 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18050 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18056 AVEIt->OtherHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18060 AVEIt->OtherHeadCode =
"";
18062 if(AVEIt->NonRepeatingShuttleLinkEntryPtr != NULL)
18064 Increment = AVEIt->NonRepeatingShuttleLinkEntryPtr - &
TrainDataVector.at(0);
18068 LinkedHeadCode = (*AVEIt->NonRepeatingShuttleLinkEntryPtr).
ServiceReference;
18071 for(
int x = LinkedHeadCode.Length(); x > 0; x--)
18073 if(LinkedHeadCode[x] ==
'/')
18075 SlashPos = LinkedHeadCode.Length() - x + 1;
18078 else if((LinkedHeadCode[x] !=
'0') && (LinkedHeadCode[x] !=
'1') && (LinkedHeadCode[x] !=
'2') && (LinkedHeadCode[x] !=
'3') &&
18079 (LinkedHeadCode[x] !=
'4') && (LinkedHeadCode[x] !=
'5') && (LinkedHeadCode[x] !=
'6') && (LinkedHeadCode[x] !=
'7') &&
18080 (LinkedHeadCode[x] !=
'8') && (LinkedHeadCode[x] !=
'8'))
18086 AVEIt->NonRepeatingShuttleLinkHeadCode = LinkedHeadCode.SubString(LinkedHeadCode.Length() - 3 - SlashPos, 4 + SlashPos);
18090 AVEIt->NonRepeatingShuttleLinkHeadCode =
"";
18095 SequenceLog +=
"1\n";
18098 std::pair<AnsiString, TServiceCallingLocsList> AllServiceCallingLocsEntry;
18104 ServiceCallingLocsList.clear();
18105 if(ActionVector.empty())
18109 if(ActionVector.at(0).SignallerControl)
18113 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18131 int HLoc = TE.
HLoc;
18132 int VLoc = TE.
VLoc;
18133 AnsiString HString;
18134 AnsiString VString;
18137 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18141 HString = AnsiString(HLoc);
18145 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18149 VString = AnsiString(VLoc);
18151 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18174 else if(AVE.
Command ==
"cdt")
18187 ServiceCallingLocsList.push_back(
"%%%" + TimeString);
18196 ServiceCallingLocsList.push_back(LName);
18200 int HLoc = TE.
HLoc;
18201 int VLoc = TE.
VLoc;
18202 AnsiString HString;
18203 AnsiString VString;
18206 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18210 HString = AnsiString(HLoc);
18214 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18218 VString = AnsiString(VLoc);
18220 ServiceCallingLocsList.push_back(HString +
'-' + VString);
18224 AllServiceCallingLocsEntry.second = ServiceCallingLocsList;
18228 SequenceLog +=
"2\n";
18257 ShowMessage(
"Unable to create a program-readable timetable - please check the timetable file validity");
18263 bool NumPlatsAtThisLocCalculated =
false, ArrivalsPrinted =
false, DeparturesPrinted =
false, AtLocsPrinted =
false;
18264 AnsiString PreviousService =
"", PreviousServiceAndRepeatNumTotalOutput =
"", BasicTime =
"", MinuteString =
"", LastAnsiTime =
"";
18265 int NumTrains = 0, NumPlats = 0, LastFrhCount = 0, FrhCount = 0, NumTrainsAtLoc = 0;
18267 SequenceLog +=
"3\n";
18274 TDateTime LastTDTime;
18275 int IncMinutes = 0;
18277 if(ActionVector.empty())
18281 if(ActionVector.at(0).SignallerControl)
18285 if(AVLast->FormatType ==
Repeat)
18287 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18295 if(AVLast->ArrivalTime != TDateTime(-1))
18297 LastTDTime = AVLast->ArrivalTime;
18299 else if(AVLast->EventTime != TDateTime(-1))
18301 LastTDTime = AVLast->EventTime;
18320 SequenceLog +=
"4\n";
18357 int IncMinutes = 0;
18359 if(ActionVector.empty())
18363 if(ActionVector.at(0).SignallerControl)
18367 if(ActionVector.at(ActionVector.size() - 1).FormatType ==
Repeat)
18369 IncMinutes = ActionVector.at(ActionVector.size() - 1).RearStartOrRepeatMins;
18371 for(
int y = 0; y < NumTrains; y++)
18385 for(
unsigned int z = 0; z < ActionVector.size(); z++)
18400 LocServiceTimesVector.push_back(TLSTEntry);
18403 AnsiString IncTime =
"", FoundStopTime =
"";
18404 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18406 if(ActionVector.at(a).FormatType ==
TimeLoc)
18417 if(FoundStopTime ==
"")
18419 throw Exception(
"Failure to determine FoundStopTime for located Snt");
18421 int WhileCount = 0;
18430 if(IncTime >= FoundStopTime)
18434 LocServiceTimesVector.push_back(TLSTEntry);
18435 if(WhileCount > 2000)
18437 throw Exception(
"While loop failed to break in 2000 loops for located Snt");
18450 int HLoc = TE.
HLoc;
18451 int VLoc = TE.
VLoc;
18452 AnsiString HString;
18453 AnsiString VString;
18456 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18460 HString = AnsiString(HLoc);
18464 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18468 VString = AnsiString(VLoc);
18470 TLSTEntry.
Location = HString +
'-' + VString;
18474 LocServiceTimesVector.push_back(TLSTEntry);
18482 LocServiceTimesVector.push_back(TLSTEntry);
18484 AnsiString IncTime =
"", FoundStopTime =
"";
18485 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18487 if(ActionVector.at(a).FormatType ==
TimeLoc)
18498 if(FoundStopTime ==
"")
18500 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18502 int WhileCount = 0;
18511 if(IncTime >= FoundStopTime)
18515 LocServiceTimesVector.push_back(TLSTEntry);
18516 if(WhileCount > 2000)
18518 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18528 bool SkipAddingMinutes =
false;
18531 LocServiceTimesVector.push_back(TLSTEntry);
18533 AnsiString IncTime =
"", FoundStopTime =
"";
18534 for(
unsigned int a = z + 1; a < ActionVector.size(); a++)
18536 if(ActionVector.at(a).FormatType ==
TimeLoc)
18544 if((a <= (z + 2)) && (FoundStopTime == TLSTEntry.
ArrTime) && ((ActionVector.at(a).LinkedTrainEntryPtr != NULL) || (ActionVector.at(a).NonRepeatingShuttleLinkEntryPtr != NULL)))
18548 LocServiceTimesVector.pop_back();
18549 SkipAddingMinutes =
true;
18554 if(FoundStopTime ==
"")
18556 throw Exception(
"Failure to determine FoundStopTime for SequenceType == StartSequence");
18558 if(!SkipAddingMinutes)
18560 int WhileCount = 0;
18569 if(IncTime >= FoundStopTime)
18573 LocServiceTimesVector.push_back(TLSTEntry);
18574 if(WhileCount > 2000)
18576 throw Exception(
"While loop failed to break in 2000 loops for SequenceType == StartSequence");
18585 if((TLSTEntry.
Location == LocServiceTimesVector.back().Location) && (TLSTEntry.
ServiceAndRepeatNum == LocServiceTimesVector.back().ServiceAndRepeatNum))
18587 if(TLSTEntry.
DepTime == LocServiceTimesVector.back().ArrTime)
18589 TLSTEntry.
ArrTime = LocServiceTimesVector.back().ArrTime;
18590 LocServiceTimesVector.pop_back();
18591 LocServiceTimesVector.push_back(TLSTEntry);
18596 LocServiceTimesVector.push_back(TLSTEntry);
18602 LocServiceTimesVector.push_back(TLSTEntry);
18621 LocServiceTimesVector.push_back(TLSTEntry);
18625 AnsiString TempDepTime = TLSTEntry.
DepTime;
18627 LocServiceTimesVector.push_back(TLSTEntry);
18629 while(TLSTEntry.
AtLocTime < TempDepTime)
18634 TLSTEntry.
DepTime = TempDepTime;
18635 LocServiceTimesVector.push_back(TLSTEntry);
18639 LocServiceTimesVector.push_back(TLSTEntry);
18650 LocServiceTimesVector.push_back(TLSTEntry);
18653 LocServiceTimesVector.push_back(TLSTEntry);
18670 AnsiString HString;
18671 AnsiString VString;
18674 HString = AnsiString(
'N') + AnsiString(HLoc).SubString(2, AnsiString(HLoc).Length() - 1);
18678 HString = AnsiString(HLoc);
18682 VString = AnsiString(
'N') + AnsiString(VLoc).SubString(2, AnsiString(VLoc).Length() - 1);
18686 VString = AnsiString(VLoc);
18688 TLSTEntry.
Location = HString +
'-' + VString;
18690 LocServiceTimesVector.push_back(TLSTEntry);
18695 AnsiString FrhTime;
18696 if(ActionVector.at(z - 1).ArrivalTime != TDateTime(-1))
18700 else if(ActionVector.at(z - 1).EventTime != TDateTime(-1))
18708 LocServiceTimesVector.push_back(TLSTEntry);
18714 LocServiceTimesVector.push_back(TLSTEntry);
18719 else if(AVE.
Command ==
"Frh-sh")
18721 if(y == NumTrains - 1)
18727 LocServiceTimesVector.push_back(TLSTEntry);
18733 LocServiceTimesVector.push_back(TLSTEntry);
18746 SequenceLog +=
"5\n";
18779 TLocServiceTimesVector::iterator Ptr1, Ptr2;
18782 AnsiString TTFileName3 = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
18783 TTFileName3 = CurDir +
"\\Formatted timetables\\Conflict Analysis " + TTFileName3 +
"; " + RailwayTitle +
"; " + TimetableTitle +
".csv";
18785 std::ofstream TTFile3(TTFileName3.c_str());
18789 ShowMessage(
"Conflict Analysis file failed to open - can't be created");
18793 if(LocServiceTimesVector.empty())
18795 ShowMessage(
"No timetabled services found");
18797 DeleteFile(TTFileName3);
18801 TTFile3 <<
"Timetable analysis for timetable: '" + TimetableTitle +
"' in conjunction with railway: '" + RailwayTitle +
"'\n";
18802 TTFile3 <<
"See user manual or on-screen help section 5.12 for detailed information.\n\n\n";
18803 SequenceLog +=
"6\n";
19032 Ptr1 = LocServiceTimesVector.begin();
19034 while(Ptr2 != LocServiceTimesVector.end())
19036 while(Ptr2->Location == Ptr1->Location)
19039 if(Ptr2 == LocServiceTimesVector.end())
19046 if(Ptr2 != LocServiceTimesVector.end())
19054 TTFile3 <<
"Arrival & pass analysis: an asterisk means that the number of same approach code arrivals and passes is equal to or greater than the number of platforms.\n";
19055 TTFile3 <<
"If the total number of arrivals and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19056 MinuteString =
" minutes";
19057 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19060 MinuteString =
" minute";
19062 TTFile3 <<
"Location,Number of,Number of,Services arriving within " << AnsiString(ArrRange) << MinuteString <<
" with their arrival times and approach codes\n";
19063 TTFile3 <<
",Platforms,Trains\n\n";
19065 Ptr1 = LocServiceTimesVector.begin();
19067 while(Ptr2 != LocServiceTimesVector.end())
19069 PreviousService =
"";
19070 NumTrainsAtLoc = 0;
19071 ServiceAndRepeatNumTotal =
"";
19073 NumPlatsAtThisLocCalculated =
false;
19075 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19077 PreviousService =
"";
19078 NumTrainsAtLoc = 0;
19079 ServiceAndRepeatNumTotal =
"";
19081 NumPlatsAtThisLocCalculated =
false;
19085 if(Ptr2 == LocServiceTimesVector.end())
19090 if(Ptr2 == LocServiceTimesVector.end())
19094 while(Ptr2->Location == Ptr1->Location)
19096 PreviousService =
"";
19097 NumTrainsAtLoc = 0;
19098 ServiceAndRepeatNumTotal =
"";
19099 BasicTime = Ptr1->ArrTime;
19100 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19104 while(!
WithinTimeRange(0, BasicTime, Ptr2->ArrTime, ArrRange) || ((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
"")))
19106 BasicTime = Ptr2->ArrTime;
19109 if(Ptr2 == LocServiceTimesVector.end())
19113 if(Ptr2->Location != Ptr1->Location)
19118 if(Ptr2 == LocServiceTimesVector.end())
19122 if(Ptr2->Location != Ptr1->Location)
19128 if((Ptr1->ArrTime ==
"") && (Ptr2->ArrTime ==
""))
19132 if(!NumPlatsAtThisLocCalculated)
19135 NumPlatsAtThisLocCalculated =
true;
19137 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19139 if(ServiceAndRepeatNumTotal ==
"")
19141 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19142 NumTrainsAtLoc = 1;
19146 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->ArrTime;
19149 PreviousService = Ptr2->ServiceAndRepeatNum;
19150 if(ServiceAndRepeatNumTotal ==
"")
19152 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19153 NumTrainsAtLoc = 1;
19157 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->ArrTime;
19161 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(2, BasicTime, Ptr2->ArrTime, ArrRange)))
19163 int MaxNumberOfSameDirections = 0;
19164 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
true, AnalysisError, MaxNumberOfSameDirections);
19169 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19173 AnsiString Asterisk =
"";
19174 if(MaxNumberOfSameDirections >= NumPlats)
19179 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19180 ArrivalsPrinted =
true;
19181 ServiceAndRepeatNumTotal =
"";
19183 if(Ptr2 == LocServiceTimesVector.end())
19187 if(Ptr2->Location != Ptr1->Location)
19192 if(Ptr2 == LocServiceTimesVector.end())
19198 if(!ArrivalsPrinted)
19200 TTFile3 <<
"Nothing to report for arrivals";
19205 SequenceLog +=
"7\n";
19210 Ptr1 = LocServiceTimesVector.begin();
19212 while(Ptr2 != LocServiceTimesVector.end())
19214 while(Ptr2->Location == Ptr1->Location)
19217 if(Ptr2 == LocServiceTimesVector.end())
19224 if(Ptr2 != LocServiceTimesVector.end())
19231 TTFile3 <<
"Departure & pass analysis: an asterisk means that the number of same exit code departures and passes is equal to or greater than the number of platforms.\n";
19232 TTFile3 <<
"If the total number of departures and passes at the same time exceeds the number of platforms the 'Trains present at location analysis' will show an asterisk.\n\n";
19233 MinuteString =
" minutes";
19234 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19237 MinuteString =
" minute";
19239 TTFile3 <<
"Location,Number of,Number of,Services departing within " << AnsiString(DepRange) << MinuteString <<
" with their departure times and exit codes\n";
19240 TTFile3 <<
",Platforms,Trains\n\n";
19242 Ptr1 = LocServiceTimesVector.begin();
19244 while(Ptr2 != LocServiceTimesVector.end())
19246 PreviousService =
"";
19247 NumTrainsAtLoc = 0;
19248 ServiceAndRepeatNumTotal =
"";
19250 NumPlatsAtThisLocCalculated =
false;
19252 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19254 PreviousService =
"";
19255 NumTrainsAtLoc = 0;
19256 ServiceAndRepeatNumTotal =
"";
19258 NumPlatsAtThisLocCalculated =
false;
19262 if(Ptr2 == LocServiceTimesVector.end())
19267 if(Ptr2 == LocServiceTimesVector.end())
19271 while(Ptr2->Location == Ptr1->Location)
19273 PreviousService =
"";
19274 NumTrainsAtLoc = 0;
19275 ServiceAndRepeatNumTotal =
"";
19276 BasicTime = Ptr1->DepTime;
19277 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19281 while(!
WithinTimeRange(3, BasicTime, Ptr2->DepTime, DepRange) || ((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
"")))
19283 BasicTime = Ptr2->DepTime;
19286 if(Ptr2 == LocServiceTimesVector.end())
19290 if(Ptr2->Location != Ptr1->Location)
19295 if(Ptr2 == LocServiceTimesVector.end())
19299 if(Ptr2->Location != Ptr1->Location)
19305 if((Ptr1->DepTime ==
"") && (Ptr2->DepTime ==
""))
19309 if(!NumPlatsAtThisLocCalculated)
19312 NumPlatsAtThisLocCalculated =
true;
19314 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19316 if(ServiceAndRepeatNumTotal ==
"")
19318 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19319 NumTrainsAtLoc = 1;
19323 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum +
"," + Ptr1->DepTime;
19326 PreviousService = Ptr2->ServiceAndRepeatNum;
19327 if(ServiceAndRepeatNumTotal ==
"")
19329 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19330 NumTrainsAtLoc = 1;
19334 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum +
"," + Ptr2->DepTime;
19338 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (!
WithinTimeRange(5, BasicTime, Ptr2->DepTime, DepRange)))
19340 int MaxNumberOfSameDirections = 0;
19341 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTArrDep(3, ServiceAndRepeatNumTotal, NumTrainsAtLoc, Ptr1->Location,
false, AnalysisError, MaxNumberOfSameDirections);
19346 throw Exception(ServiceAndRepeatNumTotalOutput.c_str());
19350 AnsiString Asterisk =
"";
19351 if(MaxNumberOfSameDirections >= NumPlats)
19356 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19357 DeparturesPrinted =
true;
19358 ServiceAndRepeatNumTotal =
"";
19360 if(Ptr2 == LocServiceTimesVector.end())
19364 if(Ptr2->Location != Ptr1->Location)
19369 if(Ptr2 == LocServiceTimesVector.end())
19375 if(!DeparturesPrinted)
19377 TTFile3 <<
"Nothing to report for departures";
19382 SequenceLog +=
"8\n";
19389 Ptr1 = LocServiceTimesVector.begin();
19391 while(Ptr2 != LocServiceTimesVector.end())
19393 while(Ptr2->Location == Ptr1->Location)
19396 if(Ptr2 == LocServiceTimesVector.end())
19403 if(Ptr2 != LocServiceTimesVector.end())
19410 TTFile3 <<
"Trains present at location analysis: an asterisk means that the number of trains at the location is greater than the number of platforms.\n\n";
19411 TTFile3 <<
"Location,Number of,Number of,Time,Services at the location at that time\n";
19412 TTFile3 <<
",Platforms,Trains,\n\n";
19413 AnsiString ServiceAndRepeatNumTotal =
"", ServiceAndRepeatNumTotalOutput =
"";
19414 Ptr1 = LocServiceTimesVector.begin();
19416 while(Ptr2 != LocServiceTimesVector.end())
19418 PreviousService =
"";
19419 ServiceAndRepeatNumTotal =
"";
19420 NumTrainsAtLoc = 0;
19422 NumPlatsAtThisLocCalculated =
false;
19425 while((Ptr2->Location != Ptr1->Location) || ((Ptr1->Location ==
"") && (Ptr2->Location ==
"")))
19427 PreviousService =
"";
19428 ServiceAndRepeatNumTotal =
"";
19429 NumTrainsAtLoc = 0;
19431 NumPlatsAtThisLocCalculated =
false;
19435 if(Ptr2 == LocServiceTimesVector.end())
19440 if(Ptr2 == LocServiceTimesVector.end())
19444 while(Ptr2->Location == Ptr1->Location)
19446 if(Ptr1->FrhMarker ==
"Frh")
19449 Ptr1->FrhMarker =
"FrhCounted";
19451 PreviousService =
"";
19452 NumTrainsAtLoc = 0;
19453 ServiceAndRepeatNumTotal =
"";
19454 if((Ptr1->Location ==
"") && (Ptr2->Location ==
""))
19458 while((Ptr2->AtLocTime != Ptr1->AtLocTime) || ((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
"")))
19461 if(Ptr1->FrhMarker ==
"Frh")
19464 Ptr1->FrhMarker =
"FrhCounted";
19467 if(Ptr2 == LocServiceTimesVector.end())
19471 if(Ptr2->Location != Ptr1->Location)
19476 if(Ptr2 == LocServiceTimesVector.end())
19480 if(Ptr2->Location != Ptr1->Location)
19484 while(Ptr2->AtLocTime == Ptr1->AtLocTime)
19486 if((Ptr1->AtLocTime ==
"") && (Ptr2->AtLocTime ==
""))
19490 if(!NumPlatsAtThisLocCalculated)
19493 NumPlatsAtThisLocCalculated =
true;
19495 if(Ptr1->ServiceAndRepeatNum != PreviousService)
19497 if(ServiceAndRepeatNumTotal ==
"")
19499 ServiceAndRepeatNumTotal = Ptr1->ServiceAndRepeatNum;
19500 NumTrainsAtLoc = 1;
19504 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr1->ServiceAndRepeatNum;
19507 PreviousService = Ptr2->ServiceAndRepeatNum;
19508 if(ServiceAndRepeatNumTotal ==
"")
19510 ServiceAndRepeatNumTotal = Ptr2->ServiceAndRepeatNum;
19511 NumTrainsAtLoc = 1;
19515 ServiceAndRepeatNumTotal = ServiceAndRepeatNumTotal +
"," + Ptr2->ServiceAndRepeatNum;
19518 if(Ptr1->FrhMarker ==
"Frh")
19521 Ptr1->FrhMarker =
"FrhCounted";
19524 if((Ptr2 == LocServiceTimesVector.end()) || (Ptr2->Location != Ptr1->Location) || (Ptr2->AtLocTime != Ptr1->AtLocTime))
19528 ServiceAndRepeatNumTotalOutput =
ConsolidateSARNTAtLoc(1, ServiceAndRepeatNumTotal, NumTrainsAtLoc);
19530 if((NumTrainsAtLoc > 1) && ((FrhCount < NumTrainsAtLoc) || (FrhCount != LastFrhCount)))
19532 AnsiString Asterisk =
"";
19533 if(NumTrainsAtLoc > NumPlats)
19540 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
"," << ServiceAndRepeatNumTotalOutput <<
'\n';
19542 else if(FrhCount == 1)
19544 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (1 remains here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19548 TTFile3 << Asterisk << Ptr1->Location <<
"," << NumPlats <<
"," << NumTrainsAtLoc <<
"," << Ptr1->AtLocTime <<
" (" << FrhCount <<
" remain here)," << ServiceAndRepeatNumTotalOutput <<
'\n';
19550 LastFrhCount = FrhCount;
19551 PreviousServiceAndRepeatNumTotalOutput = ServiceAndRepeatNumTotalOutput;
19552 AtLocsPrinted =
true;
19553 ServiceAndRepeatNumTotal =
"";
19556 if(Ptr2 == LocServiceTimesVector.end())
19560 if(Ptr2->Location != Ptr1->Location)
19565 if(Ptr2 == LocServiceTimesVector.end())
19573 TTFile3 <<
"Nothing to report for trains at locations";
19578 SequenceLog +=
"9\n";
19612 TTrainDataEntry SingleServiceEntry, PartServiceEntry, NewPartServiceEntry, TempEntry;
19617 TTFile3 <<
"Train direction analysis - consisting of train facing directions on creation and possible missing or questionable changes of direction:\n\n";
19626 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19628 SingleServiceEntry = TDE;
19630 for(
unsigned int y = 0; y < SSAV.size(); y++)
19632 if((SSAV.at(y).Command ==
"Fjo") || (SSAV.at(y).Command ==
"Frh") || (SSAV.at(y).Command ==
"Fer") || (SSAV.at(y).Command ==
"Frh-sh"))
19634 SingleServiceVector.push_back(SingleServiceEntry);
19637 else if((SSAV.at(y).Command ==
"fsp") || (SSAV.at(y).Command ==
"rsp"))
19639 PartServiceEntry = TDE;
19641 for(
unsigned int z = 0; z <= y; z++)
19646 PartServiceEntry.
ActionVector.at(z).Command =
"chr-sp";
19647 PartServiceEntry.
ActionVector.at(z).OtherHeadCode = PartServiceEntry.
ActionVector.at(z).LinkedTrainEntryPtr->ServiceReference;
19650 PartServiceVector.push_back(PartServiceEntry);
19651 if(SSAV.at(y).Command ==
"fsp")
19653 SSAV.at(y).Command =
"Front split - original service continues below";
19654 SSAV.at(y).OtherHeadCode =
"";
19656 if(SSAV.at(y).Command ==
"rsp")
19658 SSAV.at(y).Command =
"Rear split - original service continues below";
19659 SSAV.at(y).OtherHeadCode =
"";
19663 else if(SSAV.at(y).Command ==
"Fns")
19665 SSAV.at(y).Command =
"chr-Fns";
19666 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19667 PartServiceVector.push_back(SingleServiceEntry);
19670 else if(SSAV.at(y).Command ==
"Fns-sh")
19672 SSAV.at(y).Command =
"chr-Fns-sh";
19673 SSAV.at(y).OtherHeadCode = SSAV.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19674 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19675 PartServiceVector.push_back(SingleServiceEntry);
19678 else if(SSAV.at(y).Command ==
"F-nshs")
19680 SSAV.at(y).Command =
"chr-F-nshs";
19681 SSAV.at(y).OtherHeadCode = SSAV.at(y).LinkedTrainEntryPtr->ServiceReference;
19682 SSAV.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19683 PartServiceVector.push_back(SingleServiceEntry);
19689 SequenceLog +=
"10\n";
19693 AnsiString NextRef;
19694 while(!PartServiceVector.empty())
19696 PartServiceEntry = PartServiceVector.at(0);
19697 for(
unsigned int y = 0; y < PartServiceEntry.
ActionVector.size(); y++)
19699 if(PartServiceEntry.
ActionVector.at(y).Command.SubString(1,3) ==
"chr")
19701 NextRef = PartServiceEntry.
ActionVector.at(y).OtherHeadCode;
19705 bool FinishType =
true, FoundFlag =
false;
19712 for(
unsigned int y = 1; y < TempEntry.
ActionVector.size(); y++)
19716 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19720 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19726 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19727 SingleServiceVector.push_back(PartServiceVector.at(0));
19728 PartServiceVector.erase(PartServiceVector.begin());
19733 NewPartServiceEntry = PartServiceVector.at(0);
19737 PartServiceVector.push_back(NewPartServiceEntry);
19740 TempEntry.
ActionVector.at(y).Command =
"Front split - original service continues below";
19745 TempEntry.
ActionVector.at(y).Command =
"Rear split - original service continues below";
19748 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19750 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns")
19753 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19755 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19758 else if(TempEntry.
ActionVector.at(y).Command ==
"Fns-sh")
19761 TempEntry.
ActionVector.at(y).OtherHeadCode = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19762 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19763 NextRef = TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkEntryPtr->ServiceReference;
19764 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19767 else if(TempEntry.
ActionVector.at(y).Command ==
"F-nshs")
19771 TempEntry.
ActionVector.at(y).NonRepeatingShuttleLinkHeadCode =
"";
19772 NextRef = TempEntry.
ActionVector.at(y).LinkedTrainEntryPtr->ServiceReference;
19773 PartServiceVector.at(0).ActionVector.push_back(TempEntry.
ActionVector.at(y));
19781 SequenceLog += +
"11\n";
19782 throw Exception(
"Unable to find service reference " + NextRef +
" Last ref checked = " + TempEntry.
ServiceReference);
19786 if(!PartServiceVector.empty())
19788 SequenceLog +=
"12\n";
19789 throw Exception(
"PartServiceVector should be empty here - size = " + AnsiString(PartServiceVector.size()));
19791 SequenceLog +=
"13\n";
19838 bool BufferFacingUnReportedFlag =
true;
19839 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19845 SequenceLog +=
"13a\n";
19846 throw Exception(
"Repeat entry present in SingleServiceVector at position " + AnsiString(x));
19849 if((AV.at(0).Command ==
"Snt") || (AV.at(0).Command ==
"Snt-sh"))
19851 bool BufferFlag =
false;
19852 int FrontTVPos = AV.at(0).FrontStartOrRepeatDigits;
19853 int RearTVPos = AV.at(0).RearStartOrRepeatMins;
19854 AnsiString FrontLocName = AV.at(0).LocationName;
19855 int NextEntryPos, NextExitPos;
19858 if(ThisElement.
Conn[0] == RearTVPos)
19862 else if(ThisElement.
Conn[1] == RearTVPos)
19866 else if(ThisElement.
Conn[2] == RearTVPos)
19870 else if(ThisElement.
Conn[3] == RearTVPos)
19882 if(ThisElement.
Conn[ThisExitPos] == -1)
19884 SequenceLog =
"13b\n";
19885 throw Exception(
"ThisElement connects to -1 for " + TDE.
ServiceReference);
19888 NextEntryPos = ThisElement.
ConnLinkPos[ThisExitPos];
19889 if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 0) || (NextEntryPos == 2)))
19891 BufferFlag =
false;
19896 BufferFlag =
false;
19901 BufferFlag =
false;
19909 else if((NextElement.
TrackType ==
Points) && ((NextEntryPos == 1) || (NextEntryPos == 3)))
19911 ThisElement = NextElement;
19917 if(NextEntryPos == 0)
19921 else if(NextEntryPos == 1)
19925 else if(NextEntryPos == 2)
19929 else if(NextEntryPos == 3)
19934 ThisElement = NextElement;
19935 ThisExitPos = NextExitPos;
19940 if(BufferFacingUnReportedFlag)
19942 TTFile3 <<
"Train facing direction on creation analysis:-\n\n";
19943 BufferFacingUnReportedFlag =
false;
19945 TTFile3 <<
"Service " + TDE.
ServiceReference +
" facing buffers on creation\n";
19949 if(BufferFacingUnReportedFlag)
19951 TTFile3 <<
"Nothing to report for train facing directions\n\n";
19957 SequenceLog +=
"13c\n";
19960 AnsiString LocationNameToBeChecked =
"";
19961 bool MissingcdtUnreportedFlag =
true;
19963 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
19966 unsigned int y = 0;
19967 int FirstInstance = 9999, SecondInstance = 9999;
19968 bool FullBreak =
false;
19969 MarkerList.clear();
19976 while((y < TDEntry.
ActionVector.size()) && !FullBreak)
19985 LocationNameToBeChecked = TDEntry.
ActionVector.at(y).LocationName;
19987 for(
unsigned int z = y; z < TDEntry.
ActionVector.size(); z++)
19992 (AVEntry.
Command ==
"Frh-sh"))
20007 for(
unsigned int a = z; a < TDEntry.
ActionVector.size(); a++)
20013 if(TDEntry.
ActionVector.at(a).LocationName == LocationNameToBeChecked)
20015 SecondInstance = a;
20017 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20019 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20021 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20024 if(MissingcdtUnreportedFlag)
20026 TTFile3 <<
"Possibly missing changes of direction - these will be missing unless the service travels in a loop back to the locations marked:-\n\n";
20028 TTFile3 << LocationNameToBeChecked <<
" is listed twice with no direction change between in service sequence: " << Sequence <<
"\n\n";
20029 MarkerList.push_back(FirstInstance);
20030 MarkerList.push_back(SecondInstance);
20032 MissingcdtUnreportedFlag =
false;
20043 if(MissingcdtUnreportedFlag)
20045 TTFile3 <<
"Nothing to report for missing changes of direction\n\n";
20051 SequenceLog +=
"14\n";
20060 typedef std::list<AnsiString> TLocList;
20061 TLocList BackwardList, ForwardList;
20062 bool IntroLineNeeded =
true;
20063 for(
unsigned int x = 0; x < SingleServiceVector.size(); x++)
20065 unsigned int cdtPosition = 9999;
20066 AnsiString cdtLocation =
"";
20067 bool FoundSameName =
false;
20068 MarkerList.clear();
20070 for(
unsigned int y = 0; y < TDEntry.
ActionVector.size(); y++)
20073 BackwardList.clear();
20074 ForwardList.clear();
20078 (AVEntry.
Command ==
"Frh-sh"))
20080 if(MarkerList.empty())
20087 for(
unsigned int b = 0; b < TDEntry.
ActionVector.size(); b++)
20089 if(TDEntry.
ActionVector.at(b).Command.SubString(1,3) ==
"chr")
20091 Sequence = Sequence + AnsiString(
" -> ") + TDEntry.
ActionVector.at(b).OtherHeadCode;
20095 if(IntroLineNeeded)
20097 TTFile3 <<
"Questionable change of direction analysis.\n\n";
20098 TTFile3 <<
"For marked changes of direction there are no same-name locations listed both above (up to the start or another direction change)\n";
20099 TTFile3 <<
"and below (down to the end or another direction change) but not counting the change of direction location itself.\n\n";
20100 TTFile3 <<
"These changes of direction are probably valid for movements to and from depots but all should be checked to\n";
20101 TTFile3 <<
"make sure that none has been included incorrectly:\n\n";
20102 IntroLineNeeded =
false;
20104 TTFile3 <<
"Service sequence " << Sequence <<
" contains questionable changes of direction:-\n\n";
20116 for(
int z = y - 1; z >= 0; z--)
20119 if(AVEntry2.
Command ==
"cdt")
20128 BackwardList.sort();
20129 BackwardList.unique();
20130 for(
unsigned int z = y + 1; z < TDEntry.
ActionVector.size(); z++)
20144 ForwardList.sort();
20145 ForwardList.unique();
20146 FoundSameName =
false;
20148 if(!BackwardList.empty() && !ForwardList.empty())
20150 for(TLocList::iterator BLIt = BackwardList.begin(); BLIt != BackwardList.end(); BLIt++)
20152 for(TLocList::iterator FLIt = ForwardList.begin(); FLIt != ForwardList.end(); FLIt++)
20156 FoundSameName =
true;
20163 MarkerList.push_back(cdtPosition);
20167 if(IntroLineNeeded)
20169 TTFile3 <<
"Nothing to report for questionable changes of direction\n\n";
20187 SequenceLog +=
"15\n";
20193 catch(
const Exception &e)
20195 AnsiString TTErrorFileName =
"Analysis Error.txt";
20196 TTErrorFileName = CurDir +
"\\Formatted timetables\\" + TTErrorFileName;
20197 std::ofstream TTError(TTErrorFileName.c_str());
20200 ShowMessage(
"Analysis error file failed to open - can't be created");
20204 AnsiString TimeNow = TDateTime::CurrentDateTime().FormatString(
"dd-mm-yyyy hh.nn.ss");
20205 TTError << TimeNow.c_str() <<
'\n' << ArrRange <<
'\n' << ArrChecked <<
'\n' << DepRange <<
'\n' <<
20206 DepChecked <<
'\n' << AtLocChecked <<
'\n' << SequenceLog <<
'\n' << AnsiString(e.Message);
20209 ShowMessage(
"Error in Conflict Analysis: A file called 'Analysis Error.txt' has been created in your Formatted timetables folder. Please send this file together with your railway and timetable files to railwayfeedback@gmail.com for investigation - many thanks");
20219 if((SSVectorNumber < 0) || ((
unsigned int)SSVectorNumber >= SingleServiceVector.size()))
20221 throw Exception(
"SSVectorNumber out of range, = " + AnsiString(SSVectorNumber) +
", Vector size = " + SingleServiceVector.size());
20223 TTrainDataEntry SingleService = SingleServiceVector.at(SSVectorNumber);
20225 VecFile <<
",Initial service reference " << SingleService.
ServiceReference +
'\n';
20226 AnsiString Marker =
"";
20227 for(
unsigned int x = 0; x < SingleService.
ActionVector.size(); x++)
20230 for(
TNumListIterator MLIt = MarkerList.begin(); MLIt != MarkerList.end(); MLIt++)
20232 if(
int(x) == *MLIt)
20262 if(AVE.
Command.SubString(1,3) ==
"chr")
20271 AVE.
Command =
"Change of service to ";
20273 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"Fns-sh")
20275 AVE.
Command =
"Change to shuttle finishing service";
20277 if(AVE.
Command.SubString(5, AVE.
Command.Length() - 4) ==
"F-nshs")
20304 AnsiString ListOfExits =
"";
20313 VecFile << Marker <<
"Frh" <<
'\n';
20328 for(
unsigned int x = 0; x < Vector.size(); x++)
20331 if(Vector.at(x).ServiceReference == HeadCode)
20333 if(Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1).FormatType ==
Repeat)
20335 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 2);
20338 FinishType =
false;
20343 TActionVectorEntry AVE = Vector.at(x).ActionVector.at(Vector.at(x).ActionVector.size() - 1);
20346 FinishType =
false;
20351 return(Vector.at(x));
20355 return(Vector.at(Vector.size() - 1));
20364 if((Time1 ==
"") || (Time2 ==
""))
20369 int Mins = Time1.SubString(4,2).ToInt();
20370 int Hours = Time1.SubString(1,2).ToInt();
20371 int Time1Mins = (Hours * 60) + Mins;
20372 Mins = Time2.SubString(4,2).ToInt();
20373 Hours = Time2.SubString(1,2).ToInt();
20374 int Time2Mins = (Hours * 60) + Mins;
20375 if(abs(Time1Mins - Time2Mins) <= MinuteRange)
20387 bool &AnalysisError,
int &MaxNumberOfSameDirections)
20394 AnsiString Output =
"", OneService =
"", TempStr1 =
"", TempStr2 =
"";
20396 std::list<AnsiString> ServiceList;
20398 bool EvenComma =
false;
20399 for(
int x = 1; x <= Input.Length(); x++)
20401 TempStr1 = Input[x];
20402 if(TempStr1 == AnsiString(
',') && EvenComma)
20408 TempStr2 += Input[x];
20410 if(TempStr1 == AnsiString(
','))
20412 EvenComma = !EvenComma;
20416 while(TempStr2.Length() > 0)
20418 SCPos = TempStr2.Pos(
';');
20421 OneService = TempStr2.SubString(1, SCPos - 1);
20422 ServiceList.push_back(OneService);
20423 TempStr2 = TempStr2.SubString(SCPos + 1, TempStr2.Length() - SCPos);
20427 ServiceList.push_back(TempStr2);
20431 ServiceList.sort();
20432 ServiceList.unique();
20433 NumTrainsAtLoc = ServiceList.size();
20436 int DirectionMarker = 0;
20438 std::list<AnsiString>::iterator SLIt, SLIt1, SLIt2, SLIt3;
20440 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20442 *SLIt = *SLIt +
"&0";
20444 SLIt3 = ServiceList.end();
20446 AnsiString ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatInfo1, RepeatInfo2;
20447 int AmpersandPos, SpacePos, CommaPos1, CommaPos2, RepeatNum1, RepeatNum2;
20448 TAllServiceCallingLocsMap::iterator ASCLIt1, ASCLIt2;
20450 MaxNumberOfSameDirections = 0;
20451 int SameDirectionCount = 0;
20453 for(std::list<AnsiString>::iterator SLIt1 = ServiceList.begin(); SLIt1 != SLIt3; SLIt1++)
20457 if(SLIt1->SubString(SLIt1->Length() - 1, 2) != AnsiString(
"&0"))
20463 CommaPos1 = SLIt1->Pos(
',');
20464 ServiceRef1 = SLIt1->SubString(1, CommaPos1 - 1);
20466 SpacePos = ServiceRef1.Pos(
' ');
20470 RepeatInfo1 = ServiceRef1.SubString(SpacePos + 2, ServiceRef1.Length() - SpacePos - 2);
20471 ServiceRef1 = ServiceRef1.SubString(1, SpacePos - 1);
20472 if(RepeatInfo1[1] ==
'F')
20478 SpacePos = RepeatInfo1.Pos(
' ');
20479 RepeatNum1 = RepeatInfo1.SubString(SpacePos + 1, RepeatInfo1.Length() - SpacePos).ToInt();
20482 AnsiTime1 = SLIt1->SubString(CommaPos1 + 1, SLIt1->Length() - CommaPos1);
20484 AmpersandPos = AnsiTime1.Pos(
'&');
20485 AnsiTime1 = AnsiTime1.SubString(1, AmpersandPos - 1);
20490 throw Exception(
"ASCLIt1 Error in " + Input);
20492 ServiceCallingLocsList1 = ASCLIt1->second;
20493 AmpersandPos = SLIt1->Pos(
'&');
20494 *SLIt1 = SLIt1->SubString(1, AmpersandPos);
20495 *SLIt1 = *SLIt1 + AnsiString(++DirectionMarker);
20497 SameDirectionCount = 1;
20498 for(SLIt2 = SLIt; SLIt2 != ServiceList.end(); SLIt2++)
20500 CommaPos2 = SLIt2->Pos(
',');
20501 ServiceRef2 = SLIt2->SubString(1, CommaPos2 - 1);
20503 SpacePos = ServiceRef2.Pos(
' ');
20507 RepeatInfo2 = ServiceRef2.SubString(SpacePos + 2, ServiceRef2.Length() - SpacePos - 2);
20508 ServiceRef2 = ServiceRef2.SubString(1, SpacePos - 1);
20509 if(RepeatInfo2[1] ==
'F')
20515 SpacePos = RepeatInfo2.Pos(
' ');
20516 RepeatNum2 = RepeatInfo2.SubString(SpacePos + 1, RepeatInfo2.Length() - SpacePos).ToInt();
20519 AnsiTime2 = SLIt2->SubString(CommaPos2 + 1, SLIt2->Length() - CommaPos2);
20521 AmpersandPos = AnsiTime2.Pos(
'&');
20522 AnsiTime2 = AnsiTime2.SubString(1, AmpersandPos - 1);
20527 throw Exception(
"ASCLIt2 Error in " + Input);
20529 ServiceCallingLocsList2 = ASCLIt2->second;
20531 if(
SameDirection(0, ServiceRef1, ServiceRef2, AnsiTime1, AnsiTime2, RepeatNum1, RepeatNum2, ServiceCallingLocsList1, ServiceCallingLocsList2, Location, Arrival))
20533 int AmpersandPos = SLIt2->Pos(
'&');
20534 *SLIt2 = SLIt2->SubString(1, AmpersandPos);
20535 *SLIt2 = *SLIt2 + AnsiString(DirectionMarker);
20536 SameDirectionCount++;
20539 if(SameDirectionCount > MaxNumberOfSameDirections)
20541 MaxNumberOfSameDirections = SameDirectionCount;
20546 if(SLIt3->SubString(SLIt3->Length() - 1, 2) == AnsiString(
"&0"))
20549 AmpersandPos = SLIt3->Pos(
'&');
20550 *SLIt3 = SLIt3->SubString(1, AmpersandPos);
20551 *SLIt3 = *SLIt3 + AnsiString(++DirectionMarker);
20554 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20557 AmpersandPos = SLIt->Pos(
'&');
20558 AnsiString DirectionMarkerString = SLIt->SubString(AmpersandPos + 1, SLIt->Length() - AmpersandPos);
20559 AnsiString ServiceWithoutMarker = SLIt->SubString(1, AmpersandPos - 1);
20560 DirectionMarker = DirectionMarkerString.ToInt();
20561 AnsiString DirectionSuffix =
"";
20563 if(DirectionMarker < 27)
20565 c = 64 + DirectionMarker;
20566 DirectionSuffix =
"," + AnsiString(c);
20568 else if(DirectionMarker < 53)
20570 c = 65 + DirectionMarker - 27;
20571 DirectionSuffix =
",A" + AnsiString(c);
20575 DirectionSuffix =
",?";
20577 *SLIt = ServiceWithoutMarker + DirectionSuffix;
20580 for(SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20582 Output = Output + *SLIt +
",";
20584 if(Output.Length() > 0)
20586 Output = Output.SubString(1, Output.Length() - 1);
20592 catch(
const Exception &e)
20594 AnalysisError =
true;
20606 AnsiString InternalInput = Input, Output =
"", OneService =
"";
20608 std::list<AnsiString> ServiceList;
20610 while(InternalInput.Length() > 0)
20612 CommaPos = InternalInput.Pos(
',');
20615 OneService = InternalInput.SubString(1, CommaPos - 1);
20616 ServiceList.push_back(OneService);
20617 InternalInput = InternalInput.SubString(CommaPos + 1, InternalInput.Length() - CommaPos);
20621 ServiceList.push_back(InternalInput);
20622 InternalInput =
"";
20626 ServiceList.sort();
20627 ServiceList.unique();
20628 NumTrainsAtLoc = ServiceList.size();
20629 for(std::list<AnsiString>::iterator SLIt = ServiceList.begin(); SLIt != ServiceList.end(); SLIt++)
20631 Output = Output + *SLIt +
",";
20633 if(Output.Length() > 0)
20635 Output = Output.SubString(1, Output.Length() - 1);
20648 AnsiString(RepeatNum1) +
"," + AnsiString(RepeatNum2) +
"," + Location);
20650 std::list<AnsiString>::iterator LP1, LP2, ListPtr1, ListPtr2, LocPtr1, LocPtr2;
20655 bool LocFound =
false;
20656 AnsiString Ref1 = Ref1In, Ref2 = Ref2In;
20658 TDateTime FirstServiceTime;
20661 int Ref1Target = 0, Ref1Count = 0;
20662 int Ref2Target = 0, Ref2Count = 0;
20680 for(ListPtr1 = List1.begin(); ListPtr1 != List1.end(); ListPtr1++)
20683 if((*ListPtr1) == Location)
20685 LocPtr1 = ListPtr1;
20688 if(ListPtr1->SubString(1, 3) ==
"%%%")
20690 AnsiString CDTTime = ListPtr1->SubString(4, 5);
20695 FirstServiceTime = TDateTime(-1);
20696 bool BreakFlag =
false;
20699 if(TDVIt->ServiceReference == Ref1)
20701 if(Ref1Target > Ref1Count)
20706 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20707 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20711 FirstServiceTime = AVIt->EventTime;
20717 FirstServiceTime = AVIt->ArrivalTime;
20723 FirstServiceTime = AVIt->DepartureTime;
20734 if(IncMinutes == -1)
20736 throw Exception(
"Failed to find service for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20738 if(FirstServiceTime == TDateTime(-1))
20740 throw Exception(
"Failed to find first service time for ServiceRef1 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20744 if(!Arrival && (Time1 == CDTTime))
20749 if(Arrival && (Time1 == CDTTime))
20753 if(Time1 > CDTTime)
20758 if(Time1 < CDTTime)
20771 for(ListPtr2 = List2.begin(); ListPtr2 != List2.end(); ListPtr2++)
20773 if((*ListPtr2) == Location)
20775 LocPtr2 = ListPtr2;
20778 if(ListPtr2->SubString(1, 3) ==
"%%%")
20780 AnsiString CDTTime = ListPtr2->SubString(4, 5);
20785 FirstServiceTime = TDateTime(-1);
20786 bool BreakFlag =
false;
20789 if(TDVIt->ServiceReference == Ref2)
20791 if(Ref2Target > Ref2Count)
20796 IncMinutes = TDVIt->ActionVector.back().RearStartOrRepeatMins;
20797 for(TActionVector::iterator AVIt = TDVIt->ActionVector.begin(); AVIt != TDVIt->ActionVector.end(); AVIt++)
20801 FirstServiceTime = AVIt->EventTime;
20807 FirstServiceTime = AVIt->ArrivalTime;
20813 FirstServiceTime = AVIt->DepartureTime;
20824 if(IncMinutes == -1)
20826 throw Exception(
"IncMinutes -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20828 if(FirstServiceTime == TDateTime(-1))
20830 throw Exception(
"First service time -1 for ServiceRef2 in SameDirection " + Ref1In +
" " + Ref2In +
" " + Time1 +
" " + Time2 +
" " + AnsiString(RepeatNum1) +
" " + AnsiString(RepeatNum2) +
" " + Location);
20834 if(!Arrival && (Time2 == CDTTime))
20839 if(Arrival && (Time2 == CDTTime))
20843 if(Time2 > CDTTime)
20848 if(Time2 < CDTTime)
20863 LP1 = List1.begin();
20865 for(ListPtr1 = LocPtr1; ListPtr1 != LP1; ListPtr1--)
20867 if(ListPtr1 == List1.begin())
20871 if(ListPtr1->SubString(1, 3) ==
"%%%")
20878 LP2 = List2.begin();
20880 for(ListPtr2 = LocPtr2; ListPtr2 != LP2; ListPtr2--)
20882 if(ListPtr2 == List2.begin())
20886 if(ListPtr2->SubString(1, 3) ==
"%%%")
20896 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20898 if(ListPtr1 == LocPtr1)
20902 if(ListPtr1->SubString(1, 3) ==
"%%%")
20906 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20908 if(ListPtr2 == LocPtr2)
20912 if(ListPtr2->SubString(1, 3) ==
"%%%")
20916 if((*ListPtr1) == (*ListPtr2))
20933 for(ListPtr1 = LP1; ListPtr1 != List1.end(); ListPtr1++)
20935 if(ListPtr1 == List1.end())
20939 if(ListPtr1->SubString(1, 3) ==
"%%%")
20943 for(ListPtr2 = LP2; ListPtr2 != List2.end(); ListPtr2++)
20945 if(ListPtr2 == List2.end())
20949 if(ListPtr2->SubString(1, 3) ==
"%%%")
20953 if((*ListPtr1) == (*ListPtr2))
20970 if(ExitList.empty())
20976 AnsiString ExitLocList =
"";
20979 unsigned int Counter = 0;
20980 for(
TNumListIterator ELIt = ExitList.begin(); ELIt != ExitList.end(); ELIt++)
20984 if(((Counter % 6) == 0) && (Counter < (ExitList.size() - 1)))
20986 ExitLocList +=
"\n";
20989 if(StartName ==
"")
20991 if(ExitList.size() == 1)
20995 return(
" at " + ID);
21000 if(ExitList.size() < 4)
21002 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21007 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21012 for(
TNumListIterator ELIT = ExitList.begin(); ELIT != ExitList.end(); ELIT++)
21017 if(ExitList.size() < 4)
21019 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21024 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21030 if(ExitList.size() < 4)
21032 AllowedExits =
",\nallowable exit element(s): " + ExitLocList;
21033 return(
" at " + StartName);
21037 AllowedExits =
",\nallowable exit element(s):\n" + ExitLocList;
21038 return(
" at " + StartName);
21078 AnsiString FormatStr =
"####0.0";
21079 AnsiString AvLateArrMins =
"";
21080 AnsiString AvEarlyArrMins =
"";
21081 AnsiString AvLatePassMins =
"";
21082 AnsiString AvEarlyPassMins =
"";
21083 AnsiString AvLateDepMins =
"";
21084 AnsiString AvLateExitMins =
"";
21085 AnsiString AvEarlyExitMins =
"";
21088 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21121 PerfFile <<
'\n' <<
'\n' <<
"***************************************";
21122 PerfFile <<
'\n' <<
'\n' <<
"Performance summary:" <<
'\n';
21134 PerfFile <<
LateArrivals <<
" late arrivals (average " << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21138 PerfFile <<
LateArrivals <<
" late arrival (" << AvLateArrMins.c_str() <<
" min)" <<
'\n';
21146 PerfFile <<
EarlyArrivals <<
" early arrivals (average " << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21150 PerfFile <<
EarlyArrivals <<
" early arrival (" << AvEarlyArrMins.c_str() <<
" min)" <<
'\n';
21158 PerfFile <<
OnTimePasses <<
" on-time passes" <<
'\n';
21166 PerfFile <<
LatePasses <<
" late passes (average " << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21170 PerfFile <<
LatePasses <<
" late pass (" << AvLatePassMins.c_str() <<
" min)" <<
'\n';
21174 PerfFile <<
LatePasses <<
" late passes" <<
'\n';
21178 PerfFile <<
EarlyPasses <<
" early passes (average " << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21182 PerfFile <<
EarlyPasses <<
" early pass (" << AvEarlyPassMins.c_str() <<
" min)" <<
'\n';
21186 PerfFile <<
EarlyPasses <<
" early passes" <<
'\n';
21191 PerfFile <<
OnTimeExits <<
" on-time exits" <<
'\n';
21195 PerfFile <<
OnTimeExits <<
" on-time exit" <<
'\n';
21199 PerfFile <<
LateExits <<
" late exits (average " << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21203 PerfFile <<
LateExits <<
" late exit (" << AvLateExitMins.c_str() <<
" min)" <<
'\n';
21207 PerfFile <<
LateExits <<
" late exits" <<
'\n';
21211 PerfFile <<
EarlyExits <<
" early exits (average " << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21215 PerfFile <<
EarlyExits <<
" early exit (" << AvEarlyExitMins.c_str() <<
" min)" <<
'\n';
21219 PerfFile <<
EarlyExits <<
" early exits" <<
'\n';
21224 PerfFile <<
OnTimeDeps <<
" on-time departures" <<
'\n';
21228 PerfFile <<
OnTimeDeps <<
" on-time departure" <<
'\n';
21232 PerfFile <<
LateDeps <<
" late departures (average " << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21236 PerfFile <<
LateDeps <<
" late departure (" << AvLateDepMins.c_str() <<
" min)" <<
'\n';
21240 PerfFile <<
LateDeps <<
" late departures" <<
'\n';
21242 TDateTime TempExcessLCDownTime;
21256 if(TempExcessLCDownTime > TDateTime(0))
21262 AnsiString FormattedExcessLCDownMins = FormatFloat(FormatStr,
ExcessLCDownMins);
21266 PerfFile << FormattedExcessLCDownMins.c_str() <<
" excess minutes of level crossing barrier down time" <<
'\n';
21278 PerfFile <<
MissedStops <<
" missed stops" <<
'\n';
21282 PerfFile <<
MissedStops <<
" missed stop" <<
'\n';
21318 PerfFile <<
NumFailures <<
" train failures" <<
'\n';
21322 PerfFile <<
NumFailures <<
" train failure" <<
'\n';
21328 PerfFile <<
AvHoursIntValue <<
" hour mean time betweeen train failures" <<
'\n';
21332 PerfFile <<
AvHoursIntValue <<
" hours mean time betweeen train failures" <<
'\n';
21335 AnsiString AvLateMinsLocsNotReached =
"";
21341 if(LocsNotReached > 0)
21344 PerfFile << LocsNotReached <<
" locations that trains failed to reach (average lateness " << AvLateMinsLocsNotReached.c_str() <<
" min)" <<
'\n';
21348 PerfFile <<
SPADRisks <<
" SPAD risks" <<
'\n';
21352 PerfFile <<
SPADRisks <<
" SPAD risk" <<
'\n';
21364 PerfFile <<
Derailments <<
" derailments" <<
'\n';
21368 PerfFile <<
Derailments <<
" derailment" <<
'\n';
21378 PerfFile <<
'\n' <<
"***************************************" <<
'\n';
21380 bool DerailSPADFlag =
false, CrashFlag =
false;
21382 int OverallScorePercent = 100;
21383 int TotArrDepExit = 0;
21384 double TotLateMinsFactor = 1;
21385 double MissedStopAndSPADRiskFactor = 1;
21386 double NetNegFactor = 1;
21396 OverallScorePercent = 5;
21397 DerailSPADFlag =
true;
21401 OverallScorePercent = 0;
21404 if(OverallScorePercent == 100)
21409 LatenessPenalty = 0;
21415 if(TotArrDepExit > 0)
21424 NetNegFactor = TotLateMinsFactor * MissedStopAndSPADRiskFactor;
21426 OverallScorePercent = 100 * NetNegFactor;
21429 if((TotArrDepExit > 0) || DerailSPADFlag || CrashFlag)
21432 AnsiString OneFailureString =
", though the failure would account for some poor performance";
21433 AnsiString TwoOrMoreFailureString =
", though the failures would account for some poor performance";
21434 AnsiString AddedString =
"";
21437 AddedString = OneFailureString;
21441 AddedString = TwoOrMoreFailureString;
21443 PerfFile <<
"\nOverall score: " << OverallScorePercent <<
"%\n";
21444 AnsiString Rating =
"";
21445 if(OverallScorePercent == 100)
21447 Rating =
"Perfect!";
21449 else if(OverallScorePercent >= 95)
21451 Rating =
"Excellent";
21453 else if(OverallScorePercent >= 90)
21455 Rating =
"Very good";
21457 else if(OverallScorePercent >= 80)
21461 else if(OverallScorePercent >= 70)
21465 else if(OverallScorePercent >= 60)
21467 Rating =
"Unacceptable" + AddedString;
21469 else if(OverallScorePercent >= 50)
21471 Rating =
"Poor" + AddedString;
21473 else if(OverallScorePercent >= 40)
21475 Rating =
"Bad" + AddedString;
21477 else if(OverallScorePercent >= 30)
21479 Rating =
"Very bad" + AddedString;
21481 else if(OverallScorePercent >= 20)
21483 Rating =
"Terrible" + AddedString;
21485 else if(OverallScorePercent >= 10)
21487 Rating =
"Appalling" + AddedString;
21489 else if(OverallScorePercent >= 5)
21493 Rating =
"Disastrous - potential loss of life";
21498 Rating =
"Dire" + AddedString;
21501 else if(OverallScorePercent < 5)
21505 Rating =
"Catastrophic - loss of life";
21509 Rating =
"Abysmal";
21512 PerfFile <<
"Overall rating: " << Rating.c_str() <<
'\n';
21516 PerfFile <<
"\nThere were no timetabled departures, arrivals or exits so there is insufficient information to provide a performance score or rating" <<
'\n';
21518 PerfFile <<
'\n' <<
"***************************************";
21528 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21578 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21613 int IncrementalMinutes = 0;
21627 bool TrainOperatingFlag =
false;
21632 TrainOperatingFlag =
true;
21636 if(TrainOperatingFlag)
21644 for(
unsigned int z = 0; z < TDEntry.
ActionVector.size(); z++)
21691 AnsiString HeadCode;
21695 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21699 HCandTrainPosParam.first = HeadCode;
21700 HCandTrainPosParam.second = TrainID;
21702 if((TimeToAct >= 0) && (TimeToAct < 59.9))
21705 OpTimeToActMultiMapEntry.first = TimeToAct;
21706 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21735 float TimeToAct = 0;
21736 int DistanceToRedSignal = 0;
21739 ContinuationEntryVecPosVector.clear();
21740 bool LaterTrain =
false;
21744 LaterTrain =
false;
21745 if(CTEIt->second.TrainDataEntryPtr->TrainOperatingDataVector.at(CTEIt->second.RepeatNumber).RunningEntry !=
NotStarted)
21756 if(!ContinuationEntryVecPosVector.empty())
21758 for(
unsigned int x = 0; x < ContinuationEntryVecPosVector.size(); x++)
21760 if(CTEIt->second.VectorPosition == ContinuationEntryVecPosVector.at(x))
21774 ContinuationEntryVecPosVector.push_back(CTEIt->second.VectorPosition);
21775 AnsiString HeadCode = CTEIt->second.HeadCode;
21776 float CurrentStopTime;
21777 float LaterStopTime;
21778 float RecoverableTime;
21781 int DistanceToExit;
21783 bool SigControlAndCanPassRedSignal =
false;
21791 if(CTEIt->second.TrainDataEntryPtr->ActionVector.size() == 1)
21797 SigControlAndCanPassRedSignal, &CTEIt->second.TrainDataEntryPtr->ActionVector.at(AtValue),
21798 HeadCode, TrainID, CurrentStopTime, LaterStopTime, RecoverableTime, AvTrackSpeed, DistanceToExit, ExitPair);
21801 if(AvTrackSpeed < 30)
21805 if(DistanceToRedSignal == -1)
21811 int Speed = AvTrackSpeed;
21812 int MaxSpeed = int(CTEIt->second.TrainDataEntryPtr->MaxRunningSpeed);
21813 if(AvTrackSpeed > MaxSpeed)
21817 if(CTEIt->second.TrainDataEntryPtr->ActionVector.at(0).SignallerControl)
21820 Speed = CTEIt->second.TrainDataEntryPtr->SignallerSpeed;
21823 TimeToAct = LaterStopTime + DistanceToRedSignal * 3.6 / 60 / Speed;
21828 float MinsBefEnter = double(CTEIt->first -
TTClockTime) * 86400.0 / 60.0;
21829 TimeToAct += MinsBefEnter;
21832 HCandTrainPosParam.first = HeadCode;
21833 HCandTrainPosParam.second = -1 - CTEIt->second.VectorPosition;
21836 if(TimeToAct < 59.9)
21838 OpTimeToActMultiMapEntry.first = TimeToAct;
21839 OpTimeToActMultiMapEntry.second = HCandTrainPosParam;
21864 for(
unsigned int x = 0; x <
TrainVector.size(); x++)
21874 TimeToExitMultiMapEntry.first = ExitPair;
21875 TimeToExitMultiMapEntry.second = ExitInfo;
21885 bool SigControlAndCanPassRedSignal,
TActionVectorEntry *AVPtr, AnsiString HeadCode,
int TrainID,
float &CurrentStopTime,
float &LaterStopTime,
21886 float &RecoverableTime,
int &AvTrackSpeed,
int &DistanceToExit,
THVShortPair &ExitPair)
21895 AnsiString(TrackVectorPositionEntryPos) +
", " + AVPtr->
Command);
21896 int DistanceToRedSignal = 0;
21897 DistanceToExit = -1;
21898 ExitPair.first = -1;
21899 ExitPair.second = -1;
21900 int CumTrackSpeed = 0;
21902 int TrackSpeedCount = 0;
21903 float KmPerLocationStop;
21904 float MaxAllowableSpeed;
21914 int CurrentElement = TrackVectorPosition;
21915 int CurrentEntryPos = TrackVectorPositionEntryPos;
21920 CurrentStopTime = 0;
21922 RecoverableTime = 0;
21923 if(CurrentElement == -1)
21928 int CurrentExitPos;
21933 if((CurrentEntryPos == 0) || (CurrentEntryPos == 2))
21937 CurrentExitPos = 1;
21941 CurrentExitPos = 3;
21946 CurrentExitPos = 0;
21985 TimeToDepart+= 0.5;
21987 if(TimeToDepart < 0.5)
21989 TimeToDepart = 0.5;
21992 CurrentStopTime = float(TimeToDepart);
22000 CurrentStopTime = float(TimeToDepart);
22011 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22022 else if(SigControlAndCanPassRedSignal)
22027 if((NextEntryPos == 0) || (NextEntryPos == 2))
22048 CurrentElement = NextElement;
22049 CurrentEntryPos = NextEntryPos;
22050 CurrentExitPos = NextExitPos;
22062 int LaterStopNumber = 0;
22066 while(!((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0)))
22075 if(CurrentEntryPos > 1)
22090 DistanceToExit = DistanceToRedSignal;
22095 if(TrackSpeedCount > 0)
22097 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22101 if(CurrentEntryPos > 1)
22112 if(LaterStopNumber > 0)
22114 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22115 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22121 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22125 if(AvTrackSpeed > MaxAllowableSpeed)
22127 AvTrackSpeed = MaxAllowableSpeed;
22139 bool StopRequired =
false;
22156 int TrainOnElement;
22163 if(CurrentEntryPos > 1)
22172 if((TrainOnElement > -1) && (TrainOnElement != TrainID))
22181 double StopTimeDouble;
22194 if(StopTimeDouble < 0.5)
22196 StopTimeDouble = 0.5;
22200 LaterStopTime += float(StopTimeDouble);
22201 RecoverableTime += StopTimeDouble - 0.5;
22202 if((LaterStopNumber == 1) && (TrainID > -1))
22210 if((AVPtr + 1)->FormatType ==
TimeLoc)
22214 StopTimeDouble = double((AVPtr + 1)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22225 if(StopTimeDouble < 0.5)
22227 StopTimeDouble = 0.5;
22230 LaterStopTime += float(StopTimeDouble);
22231 RecoverableTime += StopTimeDouble - 0.5;
22232 if((LaterStopNumber == 1) && (TrainID > -1))
22242 StopTimeDouble = double((AVPtr + 2)->DepartureTime - AVPtr->
ArrivalTime) * 86400.0 / 60.0;
22253 if(StopTimeDouble < 0.5)
22255 StopTimeDouble = 0.5;
22258 LaterStopTime += float(StopTimeDouble);
22259 RecoverableTime += StopTimeDouble - 0.5;
22260 if((LaterStopNumber == 1) && (TrainID > -1))
22277 if(NextElement == -1)
22286 if((NextEntryPos == 0) || (NextEntryPos == 2))
22307 CurrentElement = NextElement;
22308 CurrentEntryPos = NextEntryPos;
22309 CurrentExitPos = NextExitPos;
22314 if((CurrentExitConfig ==
Signal) && (CurrentAttribute == 0))
22327 if(TrackSpeedCount > 0)
22329 MaxAllowableSpeed = CumTrackSpeed / TrackSpeedCount;
22333 if(CurrentEntryPos > 1)
22344 if(LaterStopNumber > 0)
22346 KmPerLocationStop = float(DistanceToRedSignal) / LaterStopNumber / 1000;
22347 AvTrackSpeed = (8.75 * KmPerLocationStop) + 44;
22353 AvTrackSpeed = (sqrt(
float(DistanceToRedSignal) / 1000) * 44) + 60;
22357 if(AvTrackSpeed > MaxAllowableSpeed)
22359 AvTrackSpeed = MaxAllowableSpeed;
22362 return(DistanceToRedSignal);